Swing Farbige Zelle ohne DefaultTableCellRenderer

deluxe1986

Mitglied
Hallo,
ich sitze schon seit längerem an einem Problem mit einem JTable fest und zwar schreibe ich gerade für einen Programmierbeleg an unserer FH ein Finanzkalkulationsprogramm.
Das Programm hat eine Gesamtübersicht für die einzelnen Konten und mehrere Unterkontenansichten die alle auf mehreren Tabs verteilt sind. Die Eingabe einer neuen Zeile erfolgt über ein weiteres Dialogfenster wo die gewünschten Werte eingetragen werden. Wenn nun ein negativer Betrag eingegeben wird soll dieser in dem Table rot dargestellt werden. Dies klappt schon mal soweit das wenn ein negativer Betrag eingegeben wurde das gesamte Table die Schriftfarbe rot bekommt und wenn darauf ein weiterer positiver Betrag eingegeben wird das Table wieder komplett schwarz wird. Ich habe auch schon hier im Forum gesucht jedoch komme ich einfach nicht weiter. Ich schicke euch mal den Code wo es bei mir hapert wenn ihr noch mehr Infos benötigt werde ich diesen hier auch posten jedoch ist es zu umfangreich alles zu posten da ich um die neun Tabs besitze :oops::oops:.
Ich hoffe ihr könnt mir weiterhelfen.

Java:
//
// Alle negativen Umsätze rot färben
for(int z = 0; z < Tab1.table.getRowCount(); z++)
{
       String s = (String) ((DefaultTableModel)Tab1.table.getModel()).getValueAt(z, 4);
       test = Double.valueOf(s);
       TableCellRenderer rend = Tab1.table.getCellRenderer(z, 4);
       if (test < 0 )
       {
             ((JComponent) rend).setForeground(Color.RED);
             repaint();
       }
       else
       {
             ((JComponent) rend).setForeground(Color.BLACK);
             repaint();
       }
}
 

Michael...

Top Contributor
Wenn nun ein negativer Betrag eingegeben wird soll dieser in dem Table rot dargestellt werden. Dies klappt schon mal soweit das wenn ein negativer Betrag eingegeben wurde das gesamte Table die Schriftfarbe rot bekommt und wenn darauf ein weiterer positiver Betrag eingegeben wird das Table wieder komplett schwarz wird.
Sollen jetzt nur die einzelnen Werte unterschiedlich ein gefärbt werden oder die Schriftfarbe für die gesamte Tabelle gesetzt werden?

Deine Vorgehensweise mit der Schleife ist gaaaaanz schlecht ;-) und es scheint ja nicht so zu funktionieren wie es soll.

Denke Du kommst um einen eigenen Renderer für die Spalte nicht herum.
 

deluxe1986

Mitglied
Sollen jetzt nur die einzelnen Werte unterschiedlich ein gefärbt werden oder die Schriftfarbe für die gesamte Tabelle gesetzt werden?

Es sollen nur die Zellen mit einem negativen Betrag rot gefärbt werden.

Deine Vorgehensweise mit der Schleife ist gaaaaanz schlecht ;-) und es scheint ja nicht so zu funktionieren wie es soll.

Wie kann ich es denn besser machen es sind meine ersten Versuche gewesen hab da schon einige Sachen durchprobiert.
:eek: ???:L

Denke Du kommst um einen eigenen Renderer für die Spalte nicht herum.

Hab schon mal versucht einen zu schreiben aber auch mit dem gleichen Ergebnis.
Hier mal der Code von meinem Renderer:

Java:
public class ColoredTableCellRenderer extends DefaultTableCellRenderer
{
      double test = InputDialog1.test;
      public Component getTableCellRendererComponent ( JTable table, Object value, boolean
                                                                            isSelected, boolean hasFocus, int row,
                                                                            int column)
      {
            super.getTableCellRendererComponent (table, value, isSelected, hasFocus, row, column);
            setForeground(Color.BLACK);
            if (Tab1.model.getValueAt(row, column) != null )
            {
                  if (test < 0 && column == 4)
                  {
                         setForeground(Color.RED)
                  }
             }
             return this;
      }
}

Denke ist genauso schlecht........ :eek:
Sorry für die schlechte Syntax!!!!
 

deluxe1986

Mitglied
Bekomme das irgendwie nicht eingebunden. Habs hiermit versucht:

Java:
Tab1.table.setDefaultRenderer(Object.class, new ColoredTableCellRenderer());

Klappt aber irgendwie nicht. Bekomme keine Farbe rein. Ist sicher irgendwas total simples aber ich komm einfach nicht drauf. ;(
 

Marco13

Top Contributor
Was liegen denn für Objekte in der Tabelle? Strings oder Doubles?

Probier's ggf. mal mit
TableColumn column = Tab1.table.getColumnModel().getColumn(4);
column.setCellRenderer(new ColoredTableCellRenderer());
 

deluxe1986

Mitglied
Also die Zeilen werden werden als String Vector eingefügt....

Sobald ich auf einen Button klicke frage ich die Werte mit einer for Schleife ab. Daraufhin soll der Renderer die Zellen mit den negativen Werte rot einfärben:
Java:
for(int z = 0; z < Tab1.table.getRowCount(); z++)
            		{
            			TableColumn column = Tab1.table.getColumnModel().getColumn(4);
            			column.setCellRenderer(new ColoredTableCellRenderer()); 
            		}

Aber auch dies hilft nichts :(:(
 

Marco13

Top Contributor
Hier ist mal das Beispiel "TableRenderDemo" von How to Use Tables (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Swing Components) so angepasst, dass alle Zahlen in der dritten Spalte, die kleiner als 5 sind, rot gemalt werden. Viel wird da wirklich nicht gemacht :bahnhof: Vielleicht kannst du das auf deinen Fall anpassen, oder deinen code (compilierbar) posten....


Java:
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.*;


class ColoredTableCellRenderer extends DefaultTableCellRenderer
{
      public Component getTableCellRendererComponent ( JTable table, Object value, boolean
                                                                            isSelected, boolean hasFocus, int row,
                                                                            int column)
      {
            super.getTableCellRendererComponent (table, value, isSelected, hasFocus, row, column);
            double test = Double.parseDouble(String.valueOf(value));
            setForeground(Color.BLACK);
            if (test < 5)
            {
                setForeground(Color.RED);
            }
            return this;
      }
}


/**
 * TableRenderDemo2 is just like TableDemo, except that it
 * explicitly initializes column sizes and it uses a combo box
 * as an editor for the Sport column.
 */
public class TableRenderDemo2 extends JPanel {
    private boolean DEBUG = false;

    public TableRenderDemo2() {
        super(new GridLayout(1,0));

        JTable table = new JTable(new MyTableModel());
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);

        //Create the scroll pane and add the table to it.
        JScrollPane scrollPane = new JScrollPane(table);


        TableColumn column = table.getColumnModel().getColumn(3);
        column.setCellRenderer(new ColoredTableCellRenderer());


        //Set up column sizes.
        initColumnSizes(table);

        //Fiddle with the Sport column's cell editors/renderers.
        setUpSportColumn(table, table.getColumnModel().getColumn(2));

        //Add the scroll pane to this panel.
        add(scrollPane);
    }

    /*
     * This method picks good column sizes.
     * If all column heads are wider than the column's cells'
     * contents, then you can just use column.sizeWidthToFit().
     */
    private void initColumnSizes(JTable table) {
        MyTableModel model = (MyTableModel)table.getModel();
        TableColumn column = null;
        Component comp = null;
        int headerWidth = 0;
        int cellWidth = 0;
        Object[] longValues = model.longValues;
        TableCellRenderer headerRenderer =
            table.getTableHeader().getDefaultRenderer();

        for (int i = 0; i < 5; i++) {
            column = table.getColumnModel().getColumn(i);

            comp = headerRenderer.getTableCellRendererComponent(
                                 null, column.getHeaderValue(),
                                 false, false, 0, 0);
            headerWidth = comp.getPreferredSize().width;

            comp = table.getDefaultRenderer(model.getColumnClass(i)).
                             getTableCellRendererComponent(
                                 table, longValues[i],
                                 false, false, 0, i);
            cellWidth = comp.getPreferredSize().width;

            if (DEBUG) {
                System.out.println("Initializing width of column "
                                   + i + ". "
                                   + "headerWidth = " + headerWidth
                                   + "; cellWidth = " + cellWidth);
            }

            column.setPreferredWidth(Math.max(headerWidth, cellWidth));
        }
    }

    public void setUpSportColumn(JTable table,
                                 TableColumn sportColumn) {
        //Set up the editor for the sport cells.
        JComboBox comboBox = new JComboBox();
        comboBox.addItem("Snowboarding");
        comboBox.addItem("Rowing");
        comboBox.addItem("Knitting");
        comboBox.addItem("Speed reading");
        comboBox.addItem("Pool");
        comboBox.addItem("None of the above");
        sportColumn.setCellEditor(new DefaultCellEditor(comboBox));

        //Set up tool tips for the sport cells.
        DefaultTableCellRenderer renderer =
                new DefaultTableCellRenderer();
        renderer.setToolTipText("Click for combo box");
        sportColumn.setCellRenderer(renderer);
    }

    class MyTableModel extends AbstractTableModel {
        private String[] columnNames = {"First Name",
                                        "Last Name",
                                        "Sport",
                                        "# of Years",
                                        "Vegetarian"};
        private Object[][] data = {
            {"Mary", "Campione",
             "Snowboarding", new Integer(5), new Boolean(false)},
            {"Alison", "Huml",
             "Rowing", new Integer(3), new Boolean(true)},
            {"Kathy", "Walrath",
             "Knitting", new Integer(2), new Boolean(false)},
            {"Sharon", "Zakhour",
             "Speed reading", new Integer(20), new Boolean(true)},
            {"Philip", "Milne",
             "Pool", new Integer(10), new Boolean(false)}
        };

        public final Object[] longValues = {"Sharon", "Campione",
                                            "None of the above",
                                            new Integer(20), Boolean.TRUE};

        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return data.length;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            return data[row][col];
        }

        /*
         * JTable uses this method to determine the default renderer/
         * editor for each cell.  If we didn't implement this method,
         * then the last column would contain text ("true"/"false"),
         * rather than a check box.
         */
        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        /*
         * Don't need to implement this method unless your table's
         * editable.
         */
        public boolean isCellEditable(int row, int col) {
            //Note that the data/cell address is constant,
            //no matter where the cell appears onscreen.
            if (col < 2) {
                return false;
            } else {
                return true;
            }
        }

        /*
         * Don't need to implement this method unless your table's
         * data can change.
         */
        public void setValueAt(Object value, int row, int col) {
            if (DEBUG) {
                System.out.println("Setting value at " + row + "," + col
                                   + " to " + value
                                   + " (an instance of "
                                   + value.getClass() + ")");
            }

            data[row][col] = value;
            fireTableCellUpdated(row, col);

            if (DEBUG) {
                System.out.println("New value of data:");
                printDebugData();
            }
        }

        private void printDebugData() {
            int numRows = getRowCount();
            int numCols = getColumnCount();

            for (int i=0; i < numRows; i++) {
                System.out.print("    row " + i + ":");
                for (int j=0; j < numCols; j++) {
                    System.out.print("  " + data[i][j]);
                }
                System.out.println();
            }
            System.out.println("--------------------------");
        }
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("TableRenderDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        TableRenderDemo2 newContentPane = new TableRenderDemo2();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
 

deluxe1986

Mitglied
Also ich habs jetzt soweit hinbekommen das er mir das rot zeichnet war eine Variable die falsch zugewiesen wurde.
Aber wenn ich anschließend einen positiven Betrag eingebe werden wieder alle Zellen schwarz.

Den Code zu posten wird n bissel schwierig da mein Code mehrere Tabs beinhaltet die auch ziemlich umfangreich sind.
Dieser Fehler sollte aber jetzt lösbar sein hoffe ich.....

Ich muss nur noch rausbekommen wie ich die Zelle angeben kann...

Ich denke das in meinem Renderer bei setForground die gesamte Spalte im Table angesprochen wird und nicht nur die eine mit dem negativen Betrag.
 

deluxe1986

Mitglied
Hab nochmal n bisschen rumgesucht und etwas gefunden wovon ich eigentlich ausgegangen bin das dies funktioniert. Aber lag wohl doch falsch..
Könnte mir jemand mal erklären warum der Renderer immernoch die komplette Spalte einfärbt steig da noch nicht ganz durch ???:L ???:L
Java:
import java.awt.Color;
import java.awt.Component;

import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;


public class ColoredTableCellRenderer extends DefaultTableCellRenderer
{
	/**
	 * 
	 */
	private static final long serialVersionUID = -1616602946582054133L;
	
	public Component getTableCellRendererComponent (JTable table, Object value,boolean isSelected,
												   boolean hasFocus, int row, int column)
	{
		super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
		setForeground(Color.BLACK);
		if (Tab1.model.getValueAt(row, column) != null)
		{
			double test = Double.valueOf(InputDialog.eingabeVierTF.getText()); 
			for (int q = 0;q < Tab1.model.getRowCount(); q++)
    		{
				if (test < 0 && column == 4)
				{
					DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) Tab1.table.getCellRenderer(q, 4);
					renderer.setForeground(Color.RED);
				}
				else
				{
					DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) Tab1.table.getCellRenderer(q, 4);
					renderer.setForeground(Color.BLACK);
				}
    		}
		}
		return this;
	}
}
 
D

Dow Jones

Gast
Na, da müsstest du doch schon fast am Ziel sein. :)

Nur der Teil innerhalb der Schleife sieht mir nach Unfug aus. Die Methode getTableCellRendererComponent wird für jede Cell einmal aufgerufen, da brauchst du keine Schleife um über die Zeilen zu iterieren (dadurch erreichst du lediglich, das alle Zellen in Spalte 4 so aussehen wie die Zelle in der letzten Zeile aussehen soll). Und der Aufruf von Tab1.table.getCellRenderer(q, 4) ist ebenfalls unnötig, da diese Funktion dir nichts anderes liefern wird als this, also eine Referenz auf deine eigene Klasse.

Ganz generell zu TableCellRenderern: Wenn ich das Prinzip richtig verstanden habe dann wird bei einer Tabelle keineswegs für jede Cell ein eigener Renderer erzeugt (was ja eine naheliegende Vermutung ist). Stattdessen wird - aus Performancegründen - für jeden darzustellenden Datentyp nur eine einzige Instanz des zugehörigen TableCellRenderers gebildet. Diese eine Instanz wird im weiteren Verlauf für alle Cells verwendet. Deswegen werden bei der Methode getTableCellRendererComponent auch die ganzen Parameter übergeben. Von der "returnten" Component (oh mann, dieses denglisch ist ja furchtbar...) wird dann nur noch die paint-Methode aufgerufen um sie in die Tabelle zu zeichnen. Anschließend findet für die nächste Cell ein erneuter Aufruf von getTableCellRendererComponent statt (welcher die Component wieder entsprechend anpasst und zurückliefert, woraufhin sie wieder gepainted wird). Tatsächlich existiert aber immer nur eine einzige Component.

Hmm, irgendwie habe ich das Gefühl das kein Mensch diese Erklärung verstanden hat... :rolleyes:

Also nochmal an einem Beispiel. Nehmen wir an du möchtest mehrere Progressbars in deiner Table haben. Dazu benötigst du nicht für jede Cell eine eigene Instanz von JProgressbar sondern du brauchst nur eine einzige Instanz, egal wieviele JProgressBars du in deinen Tabellen darstellen möchtest. Dazu schreibst du dir einen eigenen renderer der von JProgressBar erbt und das Interface TableCellRenderer implementiert (so macht man das üblicherweise; der DefaultTableCellRenderer zum Beispiel erbt von JLabel). Dieses Interface besitzt nur eine einzige Methode, nämlich besagtes getTableCellRendererComponent(...). Dein JProgressbar schaut sich in dieser Methode nun die ganzen Parameter an (für welche JTable er sich rendern soll, welche Zeile, welche Spalte, ob selektiert oder nicht etc) und passt daraufhin sein Aussehen entsprechend an. Zum Beispiel indem er seine Farbe ändert (oder seinen Fortschrittsbalken, oder was auch immer). Am Ende der Methode returnt er this, also eine Referenz auf sich selber (soll heissen: auf die einzige existierende instanz dieses CellRenderers).
Die JTable, von der aus die Methode getTableCellRendererComponent aufgerufen wurde, hat den Progressbar dabei nicht als Childwidget eingebunden, wie man das eigentlich normalerweise macht. Denn dann könnte er ja nur ein einziges mal dargestellt werden und man bräuchte für jede Cell eine neue Instanz unseres TableCellRenderers/JProgressbars. Stattdessen existiert der TableCellRenderer/JProgressbar "einfach so", und die JTable ruft lediglich dessen paint-Methode auf um die Zelle in ihrem aktuellen Zustand zeichnen zu lassen.
Die paint-Methode einer JTable sieht also in etwa so aus (die Methode JTable.getCellRenderer(...) liefert dabei ggf. die eine existierende Instanz deines tableCellRenderers/Progressbars zurück):
Java:
public void paint(Graphics g) {
     ...
     getCellRenderer( zeile 0, spalte 0 ).getTableCellRendererComponent(...zeile 0, spalte 0, selected=false...blabla...).paint();
     getCellRenderer( zeile 0, spalte 1 ).getTableCellRendererComponent(...zeile 0, spalte 1, selected=false...blabla...).paint();
     getCellRenderer( zeile 1, spalte 0 ).getTableCellRendererComponent(...zeile 1, spalte 0, selected=false...blabla...).paint();
     getCellRenderer( zeile 1, spalte 1 ).getTableCellRendererComponent(...zeile 1, spalte 1, selected=false...blabla...).paint();
     getCellRenderer( zeile 2, spalte 0 ).getTableCellRendererComponent(...zeile 2, spalte 0, selected=false...blabla...).paint();
     ...
}
Es wird also für jede Zelle die Methode getTableCellRenderer deines tableCellRenderers/JProgressbars aufgerufen, in der du deine Component äußerlich entsprechend anpassend sollst, und anschließend wird sie gepainted. Danach wird das gleiche nochmal für die nächste, übernächste, überübernachste usw. Cell gemacht.

Um jetzt nochmal auf deinen konkreten Fall zurückzukommen: Der DefaultTableCellRenderer erbt von JLabel. Du erbst vom DefaultTableCellRenderer. Infolgedessen ist dein ColoredTableCellRenderer ein JLabel (mit der einen zusätzlichen Methode getTableCellRendererComponent). Und daher kannst du innerhalb der Methode natürlilch auch auf alle Funktionen eines JLabels zugreifen (um z.B. die Farben zu ändern, ein Icon zu setzen, die Ausrichtung von left-aligned nach right-aligned zu ändern, Booleanwerte als "yo" und "nope"-Texte darzustellen, oder was immer du möchtest). Am Schluß der getTableCellRendererComponent-Methode returnst du einfach this, also die Referenz auf die eine existierende Instanz deines Renderers, und der Rest geht dann automatisch. Ein JLabel weiss ja, wie es sich zu painten hat (mitsamt den Farben, Icons, Texten etc).


So. jetzt hoffe ich nur noch das ich mich verständlich ausdrücken konnte und du das auch alles gelesen hast. ;)
(und falls dein Renderer weiterhin den Dienst verweigert bekommt er Ärger mit mir!)
 
Zuletzt bearbeitet von einem Moderator:

deluxe1986

Mitglied
Also wenn ich dich richtig verstanden habe muss ich im Renderer nur die Methode definieren was diese machen soll.
Und später an der Stelle wo die Zelle neu gezeichnet werden soll die Methode aufrufen. Ich hab dies mal so gelöst nach deinem Beispiel. Jedoch wird die Methode nicht aufgerufen. Entweder stell ich mich zu dumm an oder ich steig da einfach noch nicht hinter wie der Cell Renderer überhaupt arbeitet.:autsch:
Naja poste hier mal den Code so wie er jetzt bei mir aussieht:
Java:
import java.awt.Color;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;


public class ColoredTableCellRenderer extends DefaultTableCellRenderer
{
	/**
	 * 
	 */
	private static final long serialVersionUID = -1616602946582054133L;
	
	public Component getTableCellRendererComponent (JTable table, Object value,boolean isSelected,
												   boolean hasFocus, int row, int column)
	{
		super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
		setForeground(Color.BLACK);
		if (Tab1.model.getValueAt(row, column) != null)
		{
			double test = Double.valueOf(InputDialog.eingabeVierTF.getText()); 
			if (test < 0 && column == 4)
			{
				setForeground(Color.RED);
			}
		}
		return this;
	}
}

und der aufruf :

Java:
for (int i = 0; i < Tab1.model.getRowCount(); i++)
{
	Tab1.table.getCellRenderer(i, 4).getTableCellRendererComponent(Tab1.table,
        Tab1.model.getValueAt(i, 4), false, false, i, 4).repaint();
}

:oops::oops:
 
D

Dow Jones

Gast
Hmm - nee, so richtig verständlich habe ich mich gestern Nacht wohl wirklich nicht mehr ausgedrückt. Am besten du vergisst was ich da gestern geschrieben hatte und ich versuche es nocheinmal....

Also, ein TableCellRenderer ist schlicht und einfach nur irgendeine x-beliebige Klasse die eine Methode namens getTableCellRendererComponent(...) besitzt. Diese Methode soll eine Component zurückliefern welche den gewünschten Zelleninhalt repräsentiert. Dazu bekommt getTableCellRendererComponent(...) einen Haufen Parameter übergeben, damit du in der Methode auch genau weisst welcher Wert in welcher Tabelle an welcher Position etc. dargestellt werden soll.

Im Folgenden gehe ich mal davon aus, das in deiner Tabelle (Tab1) in Spalte 4 Doublewerte dargestellt werden sollen. Wenn du deine Tabelle entsprechend initialisiert hast dann musst du bei ihr nur noch einen gewünschten TableCellRenderer registrieren. Das kann wahlweise entweder als "Renderer für eine ganze Spalte" oder als "Renderer für einen bestimmten Datentyp" erfolgen. Wir wählen jetzt mal erstgenanntes, registrieren also einen Renderer für die gesamte Spalte 4:
Java:
Tab1.getColumnModel().getColumn(4).setCellRenderer( new MyRenderer() );
Mehr brauchen wir an der Tabelle gar nicht zu machen.

Was wir aber natürllich noch tun müssen ist den Renderer zu schreiben. Wie gesagt, es ist nur eine Klasse welche die genannte Methode besitzen und eine Component zurückgeben soll. Mehr nicht. Also machen wir uns damit auch nicht viel Streß:
Java:
public class MyRenderer implements TableCellRenderer {

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        JLabel label = new JLabel();
        label.setText( value.toString() );
        double v = (Double) value;
        if( v < 0.0 ) {
            label.setForeground(Color.RED);
        } else {
            label.setForeground(Color.BLACK);
        }
        return label;
    }
}
Hier erzeugen wir uns bei jedem Aufruf ein neues JLabel, setzen dessen Text auf den gewünschten Wert, und returnen es anschließend. Das geht, da JLabel ja eine Component ist. Ergo: Aufgabe gelöst.
(value muss in diesem Fall natürlich instanceof Double und != null sein. Aber da wir unseren Renderer ja nur für Spalte 4 registriert hatten, und in dieser ohnehin nur Doublewerte verwendet werden, spare ich mir entsprechende Überprüfungen jetzt mal)

Eigentlich brauchst du jetzt nicht mehr weiterzulesen, denn dieser Renderer erfüllt die Aufgabe schon voll und ganz. Aber die Performance ist (bei großen Tabelle) nicht so toll. Klar, wenn wir auch für jede Zelle ständig neue JLabels erzeugen und nach einmaligem Gebrauch wegwerfen...
Also verbessern wir den Renderer mal etwas. Er erbt jetzt von JLabel (ist also selber eins). Und er wird nicht für jeden Gebrauch neu erzeugt sondern nur ein einziges mal (bei unserem obigen Aufruf von setCellRenderer( new MyRenderer() ) ).
Java:
public class MyRenderer extends JLabel implements TableCellRenderer {

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        setText( value.toString() );
        double v = (Double) value;
        if( v < 0.0 ) {
            setForeground(Color.RED);
        } else {
            setForeground(Color.BLACK);
        }
        return this;
    }
}
Die Unterschiede zu unserer ersten Version sind programmiertechnisch zwar marginal, aber TableCellRenderer werden halt für gewöhnlich auf diese Art geschrieben, indem man sie von irgendwelchen Standardwidgets ableitet.

Eine weitere Möglichkeit einen Renderer zu schreiben besteht darin ihn von DefaultTableCellRenderer erben zu lassen (dadurch hat man noch ein paar Zusatzmethoden zur Verfügung die man ggf. verwenden kann). Dabei sollte man beachten, das der DefaultTableCellRenderer ebenfalls nur von JLabel abgeleitet ist, und das man sich am einfachsten in die Methode setValue(Object value) einklinkt:
Java:
public class MyRenderer extends DefaultTableCellRenderer {

    @Override
    protected void setValue(Object value) {
        super.setValue(value);
        double v = (Double) value;
        if ( v < 0.0 )
            setForeground( Color.RED );
        else
            setForeground( Color.BLACK );
    }
}

Auch hier gibt's keinen so großen Unterschied zu den vorherigen Renderern. Nutz halt einfach die Art und Weise die dir gerade am besten passt, funktionieren tun alle drei Renderer (bei mir zumindest). :)


DU rufst den Renderer überhaupt nicht auf. Brauchst du auch nicht, macht alles die JTable für dich. Du musst ihr nur eine Instanz deines Renderers zur Verfügung stellen, der Rest geht automatisch.
Also
1) eine Klasse Renderer schreiben
2) sie einmalig bei der Tabelle registrieren
3) fertig, mehr gibt's nicht zu tun. Die Tabelle ruft den Renderer nun selber auf, wann immer nötig
 

deluxe1986

Mitglied
Juhuuu es klappt!!!!!!!!!!
:applaus::applaus::applaus::applaus:
Dank dir vielmals.
Das war ja mal ne geniale Erklärung womit man auch was anfangen kann,
hab ich mir gleich erst mal ausgedruckt und ab mit in Ordner.... :toll:

Ach ja eins noch wenn ich jetzt die Schriftausrichtung nach rechts stellen möchte kann ich dies doch auch einfach im Renderer angeben oder???
Mein das jetzt mal nur technisch gesehen der Code ist mir klar!


Nochmals danke
 

Eraser

Mitglied
@Dow Jones: Super geschriebene Beschreibung und Erklärung! Hat mir auch bei einem Problem weitergeholfen. Vor allem die Erklärung, dass der Renderer eine Ableitung von JLabel ist *TUMBS UP*
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Swing Farbige Zelle ohne DefaultTableCellRenderer AWT, Swing, JavaFX & SWT 4
H JTextArea - farbige Zeilen .. bitte um Vorschläge zur Implementierung AWT, Swing, JavaFX & SWT 1
W Swing Farbige JPanels auf JFrame werden nicht gezeigt. Was mach ich falsch? AWT, Swing, JavaFX & SWT 7
C [SWT] Widget Table verliert nach Sortierung farbige / eingefärbter Background / Zellen AWT, Swing, JavaFX & SWT 3
L Swing Farbige JComboBox schreiben AWT, Swing, JavaFX & SWT 5
T jTable und farbige Spalten AWT, Swing, JavaFX & SWT 18
C JTable und farbige Zellen AWT, Swing, JavaFX & SWT 5
G Farbige Quadratein JCombobox AWT, Swing, JavaFX & SWT 5
M Farbige Linien zeichnen AWT, Swing, JavaFX & SWT 3
V JTable - farbige Boolean-Felder - geht das? AWT, Swing, JavaFX & SWT 3
G Farbige Label AWT, Swing, JavaFX & SWT 2
D Farbige JCombobox AWT, Swing, JavaFX & SWT 7
W Kleine Sub-Tabelle in SpreadsheetView-Zelle anzeigen AWT, Swing, JavaFX & SWT 9
S TableCellRender - Zelle auf editier-/anklickbar setzen AWT, Swing, JavaFX & SWT 5
F Best-Practise: JTable Text in Zelle zu groß AWT, Swing, JavaFX & SWT 2
missy72 JavaFX TableView / TableColumn / ObservableList / zwei Werte in einer Zelle AWT, Swing, JavaFX & SWT 2
HoT Einzelne Zelle in JTable Rahmen unten setzen AWT, Swing, JavaFX & SWT 24
P JavaFX aktuelle Tabellenzeile bei Choice-Box-Auswahl in Zelle ermitteln AWT, Swing, JavaFX & SWT 28
T Zelle- und die Zeile-Farbenwechsel bei der Selektion in der Tabelle AWT, Swing, JavaFX & SWT 4
P JavaFX TableView Zelle markieren AWT, Swing, JavaFX & SWT 3
W Swing JTable Zeilenumbruch innerhalb einer Zelle AWT, Swing, JavaFX & SWT 3
M Swing Automatischer Editorstart in JTable-Zelle AWT, Swing, JavaFX & SWT 5
S JavaFX TableView einzelne Zelle Layout zuweisen AWT, Swing, JavaFX & SWT 3
M Wert einer Zelle aus JTable ziehen AWT, Swing, JavaFX & SWT 4
P Fokus auf Zelle in JTable AWT, Swing, JavaFX & SWT 1
LexeB4F Zelle in JTable gezielt einfärben AWT, Swing, JavaFX & SWT 4
LexeB4F JTable mehrere Zelle selektieren und inhalte Löschen.. Ideen gesucht AWT, Swing, JavaFX & SWT 1
K Swing JTable mit ImageIcon und Text in einer Zelle AWT, Swing, JavaFX & SWT 1
E JavaFX TableView mit Rechtsklick Zelle auswählen AWT, Swing, JavaFX & SWT 8
E JTable Hintergrund von geklickter Zelle ändern AWT, Swing, JavaFX & SWT 2
J CellFactory in Abhängigkeit von anderer Zelle AWT, Swing, JavaFX & SWT 4
M JTable: Prüfen ob Zelle leer ist AWT, Swing, JavaFX & SWT 5
O Swing JTable - Zelle fokussieren AWT, Swing, JavaFX & SWT 10
L JTable selektierte Zelle in Bearbeitungs Modus AWT, Swing, JavaFX & SWT 2
H Combobox in einer einzelnen Zelle der Jtable AWT, Swing, JavaFX & SWT 2
R Swing Hintergrundfarbe der Zelle in einer JTable bei Markierung AWT, Swing, JavaFX & SWT 2
M Jtable Objecte aus Zelle AWT, Swing, JavaFX & SWT 13
M Beim Start von TableEditor Inhalt der Zelle markieren. AWT, Swing, JavaFX & SWT 2
S Swing Zelle einer JTable hervorheben (ohne CellRenderer) AWT, Swing, JavaFX & SWT 3
A JTable Zelle markieren von bis und Löschen AWT, Swing, JavaFX & SWT 6
F JTable soll mit Buttons befüllt werden, aber nicht in jede Zelle einer Spalte AWT, Swing, JavaFX & SWT 3
T DefaultTableCellRenderer Farbe bestimmter Zelle ändern AWT, Swing, JavaFX & SWT 2
GianaSisters Swing ComboBox im jTable (in bestimmter Zelle nicht über die ganze Spalte) AWT, Swing, JavaFX & SWT 4
O JButton in Zelle von JTable AWT, Swing, JavaFX & SWT 4
K Tabellen Inhalt ( Zelle ) Modifizieren AWT, Swing, JavaFX & SWT 2
J Zelle eine JTable ändern AWT, Swing, JavaFX & SWT 3
R Drag an Drop JTable Zelle AWT, Swing, JavaFX & SWT 6
T JTable, Popup Fester per Rechtsklick auf Zelle AWT, Swing, JavaFX & SWT 19
H variable Höhe einer JTextArea (als Renderer/Editor) als Zelle einer JTable AWT, Swing, JavaFX & SWT 9
C Swing JTable zeigt in jeder Zelle einer Reihe denselben Inhalt AWT, Swing, JavaFX & SWT 2
lenniii Zelle in JTable ändern AWT, Swing, JavaFX & SWT 2
J Swing JTable, jede Zelle ein anderer Title im TitledBorder AWT, Swing, JavaFX & SWT 5
D JTables, Test highlighten innerhalb einer Zelle AWT, Swing, JavaFX & SWT 5
S Swing JTable nach einer Änderung einer Zelle komplett aktualisieren. AWT, Swing, JavaFX & SWT 10
N Methode zum ermitteln der editierte Zeile/Zelle in jTable AWT, Swing, JavaFX & SWT 8
C Swing JTable Zelle mit Einfachklick editieren AWT, Swing, JavaFX & SWT 3
C JTable: Mehrere Farben in einer Zelle darstellen AWT, Swing, JavaFX & SWT 10
T Swing JTable - true zurückbekommen, wenn der Cursor in einer Zelle blinkt AWT, Swing, JavaFX & SWT 7
C JTable markierte Zelle wird bei removeRow nicht mit gelöscht AWT, Swing, JavaFX & SWT 6
Dit_ Verschiedene Icons in einer JTable-Zelle AWT, Swing, JavaFX & SWT 2
A JTable Zelle Padding AWT, Swing, JavaFX & SWT 9
R JTable Hintergrund der Zeile abhängig von Inhalt einer Zelle verändern AWT, Swing, JavaFX & SWT 3
S Swing DnD: Wie finde ich heraus, von welcher Zelle aus im JTable der Drag gestartet wurde? AWT, Swing, JavaFX & SWT 3
U LayoutManager [GBL] Component aus einer Zelle löschen AWT, Swing, JavaFX & SWT 2
E Zelle in JTable nach klick markieren AWT, Swing, JavaFX & SWT 2
O JTable Zelle mit "ENTER" in Editmode setzen AWT, Swing, JavaFX & SWT 4
eskimo328 JTable nächste Zelle nach Eingabe einer Ziffer AWT, Swing, JavaFX & SWT 5
B Swing Einzelne Zelle in JTable soll NICHT auswählbar sein AWT, Swing, JavaFX & SWT 9
A Swing JTable Icon nur in einer Zelle AWT, Swing, JavaFX & SWT 2
B Swing JTable merkt sich die zuletzt selektierte Zelle AWT, Swing, JavaFX & SWT 3
T einzelne Zelle einer JTable auswählen und Hintergrundfarbe ändern AWT, Swing, JavaFX & SWT 2
M JTable - verlassen einer Zelle AWT, Swing, JavaFX & SWT 15
R JTable Darstellen der selektierten Zelle braucht lange AWT, Swing, JavaFX & SWT 7
S JTable Probleme wenn ich Zelle verlasse AWT, Swing, JavaFX & SWT 4
P Für den Inhalt einer Zelle (aus Tabelle) STRG-C anwenden AWT, Swing, JavaFX & SWT 2
S Welches Event beim ändern einer Zelle in einer JTable AWT, Swing, JavaFX & SWT 4
S Welches Event beim auswählen einer Zelle? [JTable] AWT, Swing, JavaFX & SWT 3
A Multiple Zeilen in einer JTable Zelle AWT, Swing, JavaFX & SWT 6
W MouseListener für jede Zelle einer JTable AWT, Swing, JavaFX & SWT 4
V JTable verliert Fokus, wie offene Zelle schliessen? AWT, Swing, JavaFX & SWT 5
G jTable, spezille Zelle automatisch füllen AWT, Swing, JavaFX & SWT 13
J JTable: Einzelne Zelle selektieren AWT, Swing, JavaFX & SWT 6
T JPanel in JTable Zelle adden AWT, Swing, JavaFX & SWT 7
T JTable-Zelle mittels JFileChooser befüllen AWT, Swing, JavaFX & SWT 5
S JTable zwei Text-Zeilen in einer Zelle AWT, Swing, JavaFX & SWT 2
N JTable: Informiert werden, wenn User eine Zelle editiert hat AWT, Swing, JavaFX & SWT 2
M JTable: Editieren einer Zelle "von außen" abbreche AWT, Swing, JavaFX & SWT 2
M JTable Zelle ändern -> andere Zellen mit ändern AWT, Swing, JavaFX & SWT 5
S JCbox in Jtable Zelle nur anzeigen , wenn JCombobox ="a AWT, Swing, JavaFX & SWT 3
S Eine Zeile zu einer JTable hinzufügen wo Zelle selektiert is AWT, Swing, JavaFX & SWT 4
M JTable Zelle editieren AWT, Swing, JavaFX & SWT 2
S jTable Font einer Zelle ändern AWT, Swing, JavaFX & SWT 5
G Bei JTable eine bestimmte Zelle färben AWT, Swing, JavaFX & SWT 11
V JTable Zelle über befehl "selecten"? AWT, Swing, JavaFX & SWT 5
F Selectierung einer Zelle AWT, Swing, JavaFX & SWT 5
G JTable-Zeile/Zelle markieren und mir Shortcut in Arbeitsspei AWT, Swing, JavaFX & SWT 3
D JTable: Focus auf Zelle markiert ihren Text zum editieren AWT, Swing, JavaFX & SWT 2
S Farbe einer Zelle in JTable ändern AWT, Swing, JavaFX & SWT 13
J JList-Item ind JTable-Zelle auswählen. AWT, Swing, JavaFX & SWT 5
E TableCellEditor für jede Zelle AWT, Swing, JavaFX & SWT 4

Ähnliche Java Themen

Neue Themen


Oben