Discussion:
JTable Spalte färben
(zu alt für eine Antwort)
Patrick Stiefel
2003-11-24 19:36:52 UTC
Permalink
Hallo,

ich möchte gerne in einer JTable eine bestimmte Spalte mit farbigem
Hintergund versehen...

Ich stelle mir das so vor, daß ich einfach durch die Zeilen der Tabelle
iteriere und dann, wenn ich den Wert, den ich suche, gefunden habe , soll
die entsprechende Zeile einfach den Hintergrund geändert bekommen.


Also was ich schaffe: Die Zeile ermitteln, wo der Wert steht mit
getValueAt()... und equals-Vergleich

Dann habe ich die Zeile und jetzt ?
Kann mir jemand weiterhelfen ?

Gruß
Patrick
Stefan Wischnewski
2003-11-24 20:06:40 UTC
Permalink
Post by Patrick Stiefel
Hallo,
ich möchte gerne in einer JTable eine bestimmte Spalte mit farbigem
Hintergund versehen...
Ich stelle mir das so vor, daß ich einfach durch die Zeilen der Tabelle
iteriere und dann, wenn ich den Wert, den ich suche, gefunden habe , soll
die entsprechende Zeile einfach den Hintergrund geändert bekommen.
Lies über CellRenderer nach - anders, direkt, geht es glaube ich nicht.

Stefan
Tobias Vogele
2003-11-24 20:07:37 UTC
Permalink
Hallo,
Post by Patrick Stiefel
Hallo,
ich möchte gerne in einer JTable eine bestimmte Spalte mit farbigem
Hintergund versehen...
Du must einen eigenen TableCellRenderer schreiben. Am einfachsten leitest Du
deinen von DefaultTableCellRenderer ab. Dort überschreist Du dann die
Methode getTableCellRendererComponent (oder so ähnlich), und dort bekommst
Du immer die Werte und Koordinaten der aktuellen Zelle und kannst je nach
Wunsch setBackground mit der gewünschten Farbe aufrufen (nach dem Du am
einfachsten vorher super.getCellRendererComponent()) aufgerufen hast.

Grüße,

tobi
--
URL: http://www.wartmal.de Email: ***@wartmal.de
Martin Kersten
2003-11-24 20:21:22 UTC
Permalink
Hi Patrik,
Post by Patrick Stiefel
ich möchte gerne in einer JTable eine bestimmte Spalte mit farbigem
Hintergund versehen...
Ich stelle mir das so vor, daß ich einfach durch die Zeilen der Tabelle
iteriere und dann, wenn ich den Wert, den ich suche, gefunden habe , soll
die entsprechende Zeile einfach den Hintergrund geändert bekommen.
Also was ich schaffe: Die Zeile ermitteln, wo der Wert steht mit
getValueAt()... und equals-Vergleich
Dann habe ich die Zeile und jetzt ?
Kann mir jemand weiterhelfen ?
Diesen Wert den du jetzt hast, ist vom Model. Das Modell und die
Visualisierung der Daten des Modells sind getrennt (MVC-Pattern).
Meine Swing Kenntnisse sind etwas eingerostet, da ich seit Jahren
nur noch SWT benutze. Das was du benutzen kannst, sind
CellRenderer. Die normale Tabellenkomponente ist ein normales
Label, soweit ich mich erinnere. Auch wird jede Zeille durch ein
und das selbe Label dargestellt. (Hauptsache ich erzähl jetzt keinen
Quatsch).

Naja letztendlich läuft eine Lösung darauf hinaus, dass du den
CellRenderer erweiterst und immer, wenn ein bestimmter Wert
erreicht wird, beim Zeichnen dieser Zelle den Hintergrund setzt.

Hört sich komplizierter an, als es ist. Schnapp dir einfach dein
Swing Buch (hast keins? dann kaufen oder Bibliothek sind
unbezahlbar diese Bücher ;).

Zum setzen eines CellRenderers mußt du folgendes tun:

TableColumnModel columnModel=table.getColumnModel();
TableColumn column=columnModel.getColumn(columnIndex);
column.setCellRenderer(myRenderer);

Falls du jetzt nur einen gewissen Typ von Daten oder
Informationen ersetzen möchtest, kannst du einfach einen
CellRenderer schreiben, der einen gegebenen CellRenderer
benutzt. Oh man am besten ich zeigs dir kurz was ich meine:

Als erstes TableCellRenderer ist die Klasse die wir erweitern
müssen, wir sollten eventuell den DefaultTableCellRenderer
erweitern, da dies wohl am einfachsten wäre:

class MyTableCellRenderer extends DefaultTableCellRenderer {
TableCellRenderer defaultRenderer;
MyTableCellRenderer(defaultRenderer) {
this.defaultRenderer=defaultRenderer;
}
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Component component=
defaultRenderer.getTableCellRenderer(table,value,
isSelected,hasFocus,row,column);
if(wert von value ist was wir markieren wollen)
component.setBackground(...);
}
}

Ich denke mal, dass die Idee nun verständlicher ist.

Schau dir die TableCellRenderer an und versuchs
einmal auf diesen Weg. Falls du Probleme hast,
meld dich einfach. Das kriegen wir schon hin ;-)


Machs gut,

Martin (Kersten)
Patrick Stiefel
2003-11-25 07:32:04 UTC
Permalink
Hallo Martin,
Post by Martin Kersten
class MyTableCellRenderer extends DefaultTableCellRenderer {
TableCellRenderer defaultRenderer;
MyTableCellRenderer(defaultRenderer) {
this.defaultRenderer=defaultRenderer;
}
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Component component=
defaultRenderer.getTableCellRenderer(table,value,
isSelected,hasFocus,row,column);
if(wert von value ist was wir markieren wollen)
component.setBackground(...);
}
}
und ihn direkt im Code ohne neue Klasse wie folgt umgesetzt:

........

table.setDefaultRenderer(String.class, new TableCellRenderer() {

public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected, boolean hasFocus, int row, int
column) {

int maxrows = table.getRowCount();

for (int reihe = 0; reihe < maxrows; reihe++) {

if
(XMLClient.userDisplay.getText().equals(table.getValueAt(row,
1).toString())) {

setBackground( Color.blue );
return new JLabel((String)value, JLabel.LEFT);
}
}

return new JLabel((String)value, JLabel.LEFT);

}
});


das liefert mir in der von mir gewünschten Reihe alle Einträge rechtsbündig
*freu*. Aber leider ohne den Hintergrund zu ändern ;-((
da mache ich wohl noch was falsch ?

Gruß
Patrick
Aljoscha Rittner
2003-11-25 09:38:12 UTC
Permalink
[...DefaultTableCellRenderer...]
Post by Patrick Stiefel
........
table.setDefaultRenderer(String.class, new TableCellRenderer() {
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected, boolean hasFocus, int row, int
column) {
int maxrows = table.getRowCount();
for (int reihe = 0; reihe < maxrows; reihe++) {
if
(XMLClient.userDisplay.getText().equals(table.getValueAt(row,
1).toString())) {
setBackground( Color.blue );
return new JLabel((String)value, JLabel.LEFT);
Das ist der komplette Irrsinn. Ist dir eigentlich bewußt, was ein
Renderer ist? Die Methode getTableCellRendererComponent wird teilweise
hundert Mal aufgerufen, wenn du den Mauscursor nur über eine Zelle
bewegst.

Bitte lesen:

| http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
| http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#editrender
| http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#renderer

Gruß,
Josch.
--
Brot trocknet nicht so rasch aus, wenn man es stets in einem Eimer
Wasser lagert.
[Haushaltstips - für den nächsten Tip eine Antwort provozieren...]
Patrick Stiefel
2003-11-25 10:00:42 UTC
Permalink
Post by Aljoscha Rittner
Das ist der komplette Irrsinn. Ist dir eigentlich bewußt, was ein
Renderer ist? Die Methode getTableCellRendererComponent wird teilweise
hundert Mal aufgerufen, wenn du den Mauscursor nur über eine Zelle
bewegst.
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#renderer

habe ich mir mal angesehen...ist vom Prinzip doch das, was ich implementiert
habe.


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

Component component = this;

setBackground( Color.yellow );
setValue((String)value);

return component;
}
});


Und: so funktioniert es bei mir ja nun mit dem TableCellRenderer.

.... aber den sagst du, soll ich nicht verwenden, da er zu oft seine
Funktion ausführt ?
Oder soll ich ihn nur anders abwenden, also in eine separate Klasse packen
oder so ?

Gruß
Patrick
Aljoscha Rittner
2003-11-25 10:14:30 UTC
Permalink
Post by Aljoscha Rittner
Post by Aljoscha Rittner
Das ist der komplette Irrsinn. Ist dir eigentlich bewußt, was ein
Renderer ist? Die Methode getTableCellRendererComponent wird teilweise
hundert Mal aufgerufen, wenn du den Mauscursor nur über eine Zelle
bewegst.
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#renderer
habe ich mir mal angesehen...ist vom Prinzip doch das, was ich implementiert
habe.
Nein.
Post by Aljoscha Rittner
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected, boolean hasFocus, int row, int
column) {
Component component = this;
setBackground( Color.yellow );
setValue((String)value);
return component;
}
});
Und: so funktioniert es bei mir ja nun mit dem TableCellRenderer.
Nein.

Du gibst ständig ein *neues* JLabel zurück. Das obige Codestück gibt
immer sich selber zurück (also ein einziges Objekt).
Post by Aljoscha Rittner
.... aber den sagst du, soll ich nicht verwenden, da er zu oft seine
Funktion ausführt ?
Oder soll ich ihn nur anders abwenden, also in eine separate Klasse packen
oder so ?
Nein, du sollst nicht für jeden Stempelabdruck einen neuen Stempel
schnitzen. Von einem Renderer wird nur der akt. Grafikabdruck in die
Zelle gemalt. Es ist nicht notwendig ständig neue JLabels zu erzeugen
um unterschiedliche Abdrücke zu erhalten.

Bitte ließ dir das Tutorial mal durch und schau nicht nur die
Beispiele an.

Gruß,
Josch.
--
Kennen Sie das auch: Piekende, juckende Kekskrümel im Bett? Abhilfe
schafft Bettnässen!
Die Krümel quellen und die Schärfe wird genommen.
[Haushaltstips - für den nächsten Tip eine Antwort provozieren...]
Tobias Vogele
2003-11-25 10:17:20 UTC
Permalink
Hallo,
Post by Patrick Stiefel
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected, boolean hasFocus, int row, int
column) {
Component component = this;
setBackground( Color.yellow );
setValue((String)value);
return component;
}
});
Und: so funktioniert es bei mir ja nun mit dem TableCellRenderer.
.... aber den sagst du, soll ich nicht verwenden, da er zu oft seine
Funktion ausführt ?
Nein, das hat er nicht gesagt. Er hat gesagt, daß Deine vorige
Implementierung des TableCellRenderer schlecht war. Die obige
Implementierung ist hingegen ok.
Der entscheidende Unterschied liegt darin, daß vorher bei jedem Aufruf
von getTableCellRendererComponent() ein neues JLabel erzeugt wurde,
während hier ein Object (nämlich das this-Object vom Typ
DefaultTableCellRenderer, was von JLabel abgeleitet ist) immer wieder
verwendet wird. Ein JLabel ist aber wie alle graphischen Komponenten
relativ aufwändig zu erzeugen, so daß man hier besser eines immer wieder
benutzt. Darauf ist auch dieser Renderer-Ansatz ausgelegt.
Post by Patrick Stiefel
Oder soll ich ihn nur anders abwenden, also in eine separate Klasse packen
oder so ?
Das ist egal bzw. Geschmackssache. Wichtig ist, daß in dieser Methode
nicht immer neue graphische Komponenten oder andere umständlich zu
erzeugende Objekte erzeugt werden bzw. überhaupt keine langwierigen
Operationen vorgenommen werden.

Grüße,

tobi
Patrick Stiefel
2003-11-25 10:29:29 UTC
Permalink
Post by Tobias Vogele
Nein, das hat er nicht gesagt. Er hat gesagt, daß Deine vorige
Implementierung des TableCellRenderer schlecht war. Die obige
Implementierung ist hingegen ok.
Der entscheidende Unterschied liegt darin, daß vorher bei jedem Aufruf
von getTableCellRendererComponent() ein neues JLabel erzeugt wurde,
während hier ein Object (nämlich das this-Object vom Typ
DefaultTableCellRenderer, was von JLabel abgeleitet ist) immer wieder
verwendet wird. Ein JLabel ist aber wie alle graphischen Komponenten
relativ aufwändig zu erzeugen, so daß man hier besser eines immer wieder
benutzt. Darauf ist auch dieser Renderer-Ansatz ausgelegt.
Stimmt, darüber hatte ich auch erst gar nicht nachgedacht. Danke für die
Hilfe von Euch !!!


--> Aber von der Funktionalität her ist es so auch noch nicht ganz
korrekt...

------------------ SCHNIPP --------------

table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {

public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {

Component component = this;

setBackground( Color.yellow );
setValue((String)value);

return component;
}
});

------------------ SCHNAPP --------------

Ich habe nämlich eine Tabelle Typ AbstractTableModel...und eine Spalte ist
ein Boolean-Wert, der ja als CheckBox dargestellt wird.

Diese Spalte wird nicht mitgefärbt....;-)) Ich vermute mal das liegt am
Übergabeparameter Object.class.

Der erwischt wahrscheinlich die Combo-Box-Spalte nicht ?

Gruß
Patrick

Loading...