JCheckBox in JTable

chrsbo

Grünschnabel
Hi,

ich bin jetzt seit Stunden auf der Suche nach meinem Problem, weiß dass das viele haben und scheinbar die Lösungen auch im Netz stehen. Ich bin aber nicht clever genug sie für mein Beispiel anzuwenden.

Also ich lese Daten aus einer Datenbank aus und schreibe die in ein JTable. Unteranderem gibt es dort auch true/false werte. Diese werden erkannt und auch als Checkboxen dargestellt. Ich möchte nun eine ZEILE, die den Checkboxwert FALSE hat rot färben.

Jetzt habe ich das Problem, dass die gesamte(!!) Zeile zwar gefärbt ist, ich aber keine Checkboxen, sondern nur Text angezeigt bekomm. Wie muss ich die CellRenderer ändern?

Code:
myTable.setDefaultRenderer(Object.class, myTableCellrenderer);
myTable.setDefaultRenderer(Boolean.class, checkboxRenderer);

Hier der Code des myTableCellRenderer:
Code:
public class MyTableCellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {

    private static final int VALIDATION_COLUMN = 6;

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

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

        String status = table.getModel().getValueAt(row, VALIDATION_COLUMN).toString();

        if (status.equals("false")) {
            
            comp.setBackground(Color.RED);            
        }  
        else
            comp.setBackground(Color.BLUE);
        
        return comp;
    }
}

Hier der Code des checkBoxRenderer:
Code:
public class CheckBoxRenderer extends DefaultTableCellRenderer implements TableCellRenderer {

    private static final int VALIDATION_COLUMN = 6;

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

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

        String status = table.getModel().getValueAt(row, VALIDATION_COLUMN).toString();

        if (status.equals("false")) {
            JCheckBox checkbox = new JCheckBox();
            comp.setBackground(Color.RED);            
        }  
        else
            comp.setBackground(Color.BLUE);
        
        return comp;
    }
}

Ich entschuldige mich ernsthaft für die Redundanz des Themas, aber ich bekomm einfach keinei Lösung gefunden...

Viel Grüße
Christian
 
Hi und willkommen bei tutorials.de :),
ich habe eine Lösung gefunden. Als erstes musst du deinem TableModel sagen, welche Class er bei welcher Column zu erwarten hat:
Java:
model = new DefaultTableModel(data, columnNames) {
   /* (non-Javadoc)
   * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
   */
   @Override
   public Class<?> getColumnClass(int columnIndex) {
      return getValueAt(0, columnIndex).getClass();
   }
};

An deinem MyTableCellRenderer musst du nichts ändern. Ich habe allerdings noch die Änderung rein genommen, den Wert in einen Boolean zu verwandeln. Ist einfach besser zu verstehen und geht im Programm schneller.
Java:
public class MyTableCellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
			boolean hasFocus, int row, int column) {
		Component comp = super.getTableCellRendererComponent(
				table, value, isSelected, hasFocus, row, column
		);

		boolean status = Boolean.parseBoolean(table.getModel().getValueAt(row, 1).toString());
		if (status) {
			comp.setBackground(Color.RED);            
		} else {
			comp.setBackground(Color.BLUE);
		}
		return comp;
	}
}

So, nun fehlt noch der CheckBoxRenderer. Diesen Renderer darfst du nicht von DefaultTableCellRenderer erben lassen, sondern von JCheckBox. Damit die Zeile dann komplett aktuellisiert wird, musst du dann nur noch table.repaint() aufrufen und fertig.
Java:
public class CheckBoxRenderer extends JCheckBox implements TableCellRenderer {
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
			boolean hasFocus, int row, int column) {
		boolean status = Boolean.parseBoolean(table.getModel().getValueAt(row, 1).toString());
		setSelected(status);
		if (status) {
			setBackground(Color.RED);            
		} else {
			setBackground(Color.BLUE);
		}
		table.repaint();
		return this;
	}
}

Ich hoffe das war verstendlich erklärt. Falls du noch Fragen haben solltest, nur zu. ;)

ps.: Bitte verwende in Zukunft die [code=java]...[/code]-CodeTags, damit die Javasyntax gehighlited wird. Danke :)

Gruß

Fabio
 
Hi,

danke für die Antwort, aber ich habe leider immernoch das Problem, dass die Zelle in der sich die Checkbox befindet nicht gefärbt ist. (Die anderen Zellen der Zeile sind richtig gefärbt.)

Außerdem tritt bei

Java:
orderTable.setDefaultRenderer(Object.class, myTableCellrenderer);
orderTable.setDefaultRenderer(Boolean.class, checkboxRenderer);

Das Problem auf, dass die Checkboxen nicht den Wert aus der Datenbank übernehmen.


Bei
Java:
orderTable.setDefaultRenderer(Object.class, myTableCellrenderer);
//orderTable.setDefaultRenderer(Boolean.class, checkboxRenderer);

Werden die checkboxen richtig aktiviert gezeigt, auch die Zellen der Zeile sind richtig gefärbt, nur eben die Zelle der Checkbox nicht.

Idee? :)


PS: Danke für das nette Wilkommen heißen =)
 
Das kommt darauf an, wie dein Code nun aussieht. So ohne weiteres kann ich das nicht sagen. Da würde ich auch nur in der Luft rumstochern. ;)
 
Hi also mein Code sieht nun wie folgt aus:

TableModel:
Java:
public class MyTableModel extends AbstractTableModel {

    private String[] columnNames = {"ID", "Name", "Größe", "Preis", "Anzahl", "Tischnummer", "Abgefertigt"};
    private Object[][] data;

    public void setData(ArrayList<Order> allOrders) {
        data = new Object[allOrders.size()][7];

        for (int i = 0; i < allOrders.size(); i++) {
            for (int y = 0; y < 7; y++) {
                data[i][0] = allOrders.get(i).getID();
                data[i][1] = allOrders.get(i).getName();
                data[i][2] = allOrders.get(i).getGroesse();
                data[i][3] = allOrders.get(i).getPreis();
                data[i][4] = allOrders.get(i).getNumberOfDrink();
                data[i][5] = allOrders.get(i).getTableNumber();
                data[i][6] = allOrders.get(i).getStatus();
            }

        }
        System.out.println("");
    }
    

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

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

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

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

    public boolean isCellEditable(int row, int col) {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        if (col == 6) {
            return true;
        } else {
            return false;
        }
    }

    public void setValueAt(Object value, int row, int col) {

        if (value.toString().equals("true")) {
            data[row][col] = value;
            fireTableCellUpdated(row, col);
        }

    }

    public Class<?> getColumnClass(int col) {
        return getValueAt(0, col).getClass();
    }

}

TabelCellRenderer
Java:
public class MyTableCellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {

    private static final int VALIDATION_COLUMN = 6;

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

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

        Boolean status = Boolean.parseBoolean(table.getModel().getValueAt(row, VALIDATION_COLUMN).toString());


        if (!status) {

            comp.setBackground(Color.RED);
        } else {
            comp.setBackground(Color.BLUE);
        }

        return comp;
    }

}

CheckBoxRenderer
Java:
public class CheckBoxRenderer extends JCheckBox implements TableCellRenderer {

    private static final int VALIDATION_COLUMN = 6;

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

        Boolean status = Boolean.parseBoolean(table.getModel().getValueAt(row, VALIDATION_COLUMN).toString());

        if (!status) {
            setBackground(Color.RED);
        } else {
            setBackground(Color.BLUE);
        }
        
        table.repaint();
        return this;
    }
    

}

Beste Grüße
Christian
 
Hi,
also ich würde mal vermuten, dass das Problem an dem AbstractTableModel liegt. Versuch es mal mit dem DefaultTableModel. Da hast du auch nicht ganz so viel Tipparbeit. ;)
Java:
model = new DefaultTableModel(data, columnNames) {
			/* (non-Javadoc)
			 * @see javax.swing.table.DefaultTableModel#isCellEditable(int, int)
			 */
			@Override
			public boolean isCellEditable(int row, int column) {
				if(column == 6) {
					return true;
				}
				return false;
			}
			
			/* (non-Javadoc)
			 * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
			 */
			@Override
			public Class<?> getColumnClass(int columnIndex) {
				return getValueAt(0, columnIndex).getClass();
			}
		};

Dann sollte es auch funktionieren. Das tut es zumindest bei mir. :)

Gruß

Fabio
 
Ok, habe jetzt AbstractTableModel durch DefaultTableModel ausgetauscht und bekomme jetzt folgende Fehlermeldung:

Java:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at clickndrinkprovider.MyTableModel.getRowCount(MyTableModel.java:47)
	at javax.swing.table.DefaultTableModel.setDataVector(DefaultTableModel.java:207)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:107)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:89)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:69)
	at clickndrinkprovider.MyTableModel.<init>(MyTableModel.java:14)
	at clickndrinkprovider.NewJFrame.<init>(NewJFrame.java:28)
	at clickndrinkprovider.NewJFrame$4.run(NewJFrame.java:301)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:641)
	at java.awt.EventQueue.access$000(EventQueue.java:84)
	at java.awt.EventQueue$1.run(EventQueue.java:602)
	at java.awt.EventQueue$1.run(EventQueue.java:600)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:611)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
BUILD SUCCESSFUL (total time: 1 second)

Mit wird meine GUI nicht angezeigt, hat wohl Probleme beim Daten holen?
Der Rest vom code ist exakt gleich geblieben!

Viele Grüße
Christian
 
Das sieht ganz danach aus, dass du einen Wert zurückgeben lassen willst, der nicht vorhanden ist. Deshalb die NullPointerException.
Hast du das DefaultTableModel deinem MyTableModel extended? Oder hast du es so geschrieben wie ich?
Falls du es extended hast, schreib es bitte mal so wie ich es geschreiben habe. Und dann auch nur die zwei Methoden überschreiben, die ich auch überschrieben habe.
 
Es müsste doch auch funktionieren, wenn ich das DefaultTableModel in meiner eigenen Klasse extende? Will schon das eigene TableModel in einer eigenen Klasse haben....
 
Zurück