JTable celle háttérszíne

Fórumok

Szeretném megváltoztatni egy JTable objektum egy cellájának háttérszínét.
A neten van ezerrel példa, arra, hogy az egész oszlopnak hogyan változtassam meg.
De egyetlen cellának nem bírok rájönni hogyan.

E az egész tábláét változtatja:


tabla.setBackground(Color.blue);

Ez az egész oszlopét változtatja:


tabla.getColumnModel().getColumn(0).setCellRenderer(new BlackTableCellRenderer());

Nekem csak egyetlen cella színét kellene változtatnom.

Csinált már valaki ilyet?

Hozzászólások

A link alapján csináltam ezt a szösszenetet:


import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.Component;
import java.awt.Color;

class Program01 extends JFrame
{
  private JTable tabla;

  public Program01()
  {
    setLayout(null);

    tabla = new JTable(9, 9);
    tabla.setBounds(100, 100, 300, 200);
    int columnWidht = 20;
    int rowHeight = 25;

    for(int i=0; i<9; i++)
	tabla.getColumnModel().getColumn(i).setPreferredWidth(columnWidht);
    for(int i=0; i<9; i++)
	tabla.setRowHeight(i, rowHeight);

    tabla.setDefaultRenderer(String.class, new DefaultTableCellRenderer()
    { 
      public Component getTableCellRendererComponent(JTable table, Object value,
	      boolean isSelected, boolean hasFocus, int row, int column)
      {
        Component component = super.getTableCellRendererComponent(table, value,
	                      isSelected, hasFocus, row, column);

       	if (row == 3 && column == 3)
	    component.setBackground(isSelected ? Color.blue : Color.black);
	return component;
      }
    });

    add(tabla);

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(800, 600);
    setVisible(true);
  }
  public static void main(String args[])
  {
     new Program01();
   }
}

Persze eredetileg ez a sor:


 Component component = super.getTableCellRendererComponent(table, value,
	                      isSelected, hasFocus, row, column);

getTableCellRendererComponent() nélkül van:


 Component component = super(table, value, isSelected, hasFocus, row, column);

Akkor viszont azt mondja a fordító, hogy a super()-t a konstruktor elején kell meghívni.

Nyilván nem értek valamit.

Csak szeretnék egy-egy kockát feketére festeni. De mindez úgy hogy bármikor
megváltoztatható legyen futás közben is, ezzel a módszerrel. Nem megy.

:(

A linket azért köszönöm!

Esetleg próbáld így, de a legjobb ha megnézed az apidoc-ot hogy miért lesz ez így most jó

tabla.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

if (row == 3 && column == 3) {
component.setBackground(Color.BLUE);
} else {
component.setBackground(Color.BLACK);
}

return component;
}
});

Ebben is van okosság
http://docs.oracle.com/javase/tutorial/uiswing/components/table.html

Megoldva:


import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.Component;
import java.awt.Color;
import javax.swing.table.DefaultTableModel;

class Program01 extends JFrame
{
	private JTable tabla;

	public Program01()
	{
		setLayout(null);

		tabla = new JTable(9, 9);
		tabla.setBounds(100, 100, 300, 200);
		int columnWidht = 20;
		int rowHeight = 25;

		for(int i=0; i<9; i++)
			tabla.getColumnModel().getColumn(i).setPreferredWidth(columnWidht);
		for(int i=0; i<9; i++)
			tabla.setRowHeight(i, rowHeight);

		tabla.setDefaultRenderer(Object.class, new BlackTableCellRenderer(5,2));
		add(tabla);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(800, 600);
		setVisible(true);
	}
	public static void main(String args[])
	{
		new Program01();
	}
	public class BlackTableCellRenderer extends DefaultTableCellRenderer
	{
		private int x, y;
		public BlackTableCellRenderer(int y_, int x_)
		{
			x = x_;
			y = y_;
		}
		@Override
		public Component getTableCellRendererComponent(JTable table, Object obj, boolean isSelected, boolean hasFocus, int row, int column)
		{
			Component cell = super.getTableCellRendererComponent(table, obj, isSelected, hasFocus, row, column);
			
			if(isSelected == false)
				if(row == x && column == y)
					cell.setBackground(Color.black);
				else
					cell.setBackground(Color.white);
			return cell;
		}
	}	
}

Köszönöm a hozzászólásokat, a segítséget! Amit írtatok azok alapján ez született.

Revidiálnám ezt sikert. Valóban a topic megnyitásakor megfogalmazott példa működik. Néhány napja elkezdtem volna alkalmazni, mire kiderült, hogy nem jó, mert ezzel a módszerrel csak egyetlen cella lehet mindig fekete. Ha újabb cellát adok meg, akkor az előző fehér lesz. Ez meg nem jó így.

Kiadva az alábbi két utasítást:


tabla.setDefaultRenderer(Object.class, new BlackTableCellRenderer(2,2));
tabla.setDefaultRenderer(Object.class, new BlackTableCellRenderer(4,4));

a 2,2 cella valóban fekete lesz, de az utána következő utasítás után már csak a 4,4 cella.

A gond persze ebben metódusban van:


public Component getTableCellRendererComponent(JTable table, Object obj, boolean isSelected, boolean hasFocus, int row, int column)
{
	Component cell = super.getTableCellRendererComponent(table, obj, isSelected, hasFocus, row, column);
			
	if(!isSelected)
		if(row == x && column == y)
			cell.setBackground(Color.black);
		else
			cell.setBackground(Color.white);
	return cell;
}

Component cell kezdetű sor után kellene jó feltételeket írni. Logikusan adódna a


if( row == x && column == y)
   cell.setBackground(Color.black)

Ez viszont nem jó mert a metódus az összes cellát beállítja x, y értéktől feketére.

Van persze olyan megoldás is, hogy JLabel-eket teszek tartalomnak, és működik is. Most jön a de. Viszont akkor a táblázat nem szereti ha szöveget írok bele.

Keresztrejtvény generálás lenne a végcél, így ez nem jó. A fekete kockák mellett írni is kellene egy-egy karaktert a cellákban.

Gondoltam már arra is, hogy megrajzoltatom a fekete kockákat, hiszen tudok rajzolni a táblázatra. Ennyi erővel az már készen is lenne. De jobb lenne ha ez a fenti dolog működne és nem ilyen workround" típusú megoldást kellene használnom.

flame on
Már vagy három napja esténként ezzel szívok. Nem bírok egy jó feltétel összehozni. Egyszer ezt megoldottam már C# nyelven. Monoval is megy. De szerettem volna C#-tól valamilyen eltérő nyelvben. Jó lett volna még nekem a wxWidget bármilyen nyelven is, de ott meg nem lehet a táblázatra rajzoltatni. Néztem FreePascal (Lazarus), itt kevesebb az ismeretem, de a rövid vele töltött idő után sem tudtam színezni egy cella hátterét. Nincs a C# nyelven kívül egy nyelv, egy környezet amiben meg tudom oldani? Szerettem volna platformfüggetlenül. Azért is Java, wxWidgets, Lazarus, stb. A monora (C#) nem szeretnék visszatérni.
flam off

Gondoltam írok még ide, hátha van valakinek jó ötlete, mielőtt a táblázat felé rajzoltatom a fekete cellákat. Ötlet?


tabla.setDefaultRenderer(Object.class, new BlackTableCellRenderer(2,2));
tabla.setDefaultRenderer(Object.class, new BlackTableCellRenderer(4,4));
a 2,2 cella valóban fekete lesz, de az utána következő utasítás után már csak a 4,4 cella.

Vajon miért? :D elárulom: mert az Object.class-hoz beállítod a default renderert :) és nyilvánvaló a 4,4 felülírja a 2,2 változatot....

A megoldás 1 azaz egy db setDefaultRenderer hívás lesz, de 1 db koordi helyett sokkal, így:
tabla.setDefaultRenderer(Object.class, new BlackTableCellRenderer(feketeCellákKoordinátái));

a getTableCellRendererComponent(...) -ben pedig a feketeCellákKoordinátái lista alapján állítgatod a hátteret.
good luck...

Igaz, ez talán kevesebb munkával jár. Ennek neki is ugrottam, íme:


....
List<CoorHash> m = new Vector<CoorHash>();

m.add(setCell(2,2));
m.add(setCell(4,4));

tabla.setDefaultRenderer(Object.class, new BlackTableCellRenderer(m));
...

Létrehoztam a setCell() eljárást és a CoorHas osztályt, majd javítottam a BlackTableCellRenderer() osztályt:


CoorHash setCell(int x, int y)
{
	CoorHash m = new CoorHash();
	m.x = x;
	m.y = y;
	return m;
}

class CoorHash
{
	int x;
	int y;
}
public class BlackTableCellRenderer extends DefaultTableCellRenderer
{
	private List<CoorHash> m;
	public BlackTableCellRenderer(List<CoorHash> m_)
	{
		m = m_;
	}
	@Override
	public Component getTableCellRendererComponent(JTable table, Object obj, boolean isSelected, boolean hasFocus, int row, int col)
	{
		Component cell = super.getTableCellRendererComponent(table, obj, isSelected, hasFocus, row, col);

		int n = m.size();
			
		int i = 0;
		while(i<n && !(m.get(i).x == row && m.get(i).y ==col))
			i++;
		boolean van = false;
			
			
		if(!isSelected)
			if(i<n)
				cell.setBackground(Color.black);
			else
				cell.setBackground(Color.white);
		return cell;
	}
}

Most vagy kellene egy lehetőség (amivel megint gondban vagyok), amellyel lekérdezem a cellák aktuális színét, vagy külön nyilvántartást vezetek róluk. Mondjuk ezt az utóbbit szintén kerülni szerettem volna. De azt hiszem marad akkor a külön nyilvántartás.

Krumplicska számára is köszönöm a választ!

Lehet neked ez kell igazából és nem a table.setDefaultRenderer(class,renderer):
http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#ed…

To specify a cell-specific renderer, you need to define a JTable subclass that overrides the getCellRenderer method. For example, the following code makes the first cell in the first column of the table use a custom renderer:

TableCellRenderer weirdRenderer = new WeirdRenderer();
table = new JTable(...) {
public TableCellRenderer getCellRenderer(int row, int column) {
if ((row == 0) && (column == 0)) {
return weirdRenderer;
}
// else...
return super.getCellRenderer(row, column);
}
};

A rendererben még lehet instanceof-al vizsgálgatni a cella típusát és aszerint változtatni a színt, bár nekem az kicsit büdös most :D
Csináltam egy példát itt találod:
http://pastebin.com/tTksQ9eJ
good luck

update:
Na most már biztos vagyok benne, hogy a JTable.getCellRenderer(x,y)-ot kell felülírnod és simán a koordi vagy a modellből a cella típusától függően más-más cellrenderert kell visszaadnod, így a rendererek is egyszerűek maradnak, mert nem kell beléjük semmi cella típus vizsgálgatás, csak simán háttérszín beállítás.