è possibile modificare una proprietà della JTable tramite il metodo setDefaultRenderer(). Nel caso dello screenshot sopra, la tabella è divisa in un numero indeterminato di righe, e n° 6 colonne. La colonna interessata a visualizzare le celle con una checkbox è la prima, quindi il mio interesse è di modificare la colonna in questione. Per prima cosa definiamo la classe CheckBoxTableCellRenderer, ovvero una classe che eredita da JCheckBox e che si appoggià all'interfaccia JTableCellRenderer. Quest'ultima contiene solamente un metodo: getTableCellRendererComponent(), che noi definiamo a nostro piacere e che deve ritornare il componente (oggetto grafico) che vogliamo visualizzare nella casella, dunque il JCkeckBox
import javax.swing.JCheckBox;
import javax.swing.table.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.SwingConstants;
import java.awt.Component;
import java.awt.Insets;
import javax.swing.JTable;
import javax.swing.UIManager;
class CheckBoxTableCellRenderer
extends JCheckBox
implements TableCellRenderer {
Border noFocusBorder;
Border focusBorder;
public CheckBoxTableCellRenderer() {
super();
setContentAreaFilled(true); // sfondo opaco
setBorderPainted(true);
setHorizontalAlignment(SwingConstants.CENTER); (allineamento orizzontale centrato)
setVerticalAlignment(SwingConstants.CENTER); (allineamento verticale centrato)
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected,
boolean hasFocus,
int row, int column) {
if(table == null) {
//operazioni da fare nel caso la tabella non contenga alcun record
}
else {
if (isSelected) { //variabile locale che è vera se la riga è selezionata
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
}
else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setEnabled(table.isEnabled());
//questo pezzo di codice agisce sul bordo, per eliminare l'effetto "tasto"
if (hasFocus) {
if (focusBorder == null) {
focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
}
setBorder(focusBorder);
}
else {
if (noFocusBorder == null) {
if (focusBorder == null) {
focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
}
if (focusBorder != null) {
Insets n = focusBorder.getBorderInsets(this);
noFocusBorder = new EmptyBorder(n);
}
}
setBorder(noFocusBorder);
}
//seleziona o meno il JCheckBox, in base al valore della cella (riga selezionata o meno)
setSelected(Boolean.TRUE.equals(value));
}
//ritorna il JCheckBox
return this;
}
}
Definita la classe CheckBoxTableCellRenderer, dobbiamo adesso adottarla nella JTable.
Supponiamo di avere una JTable di nome "table", quindi:
TableColumnModel tcm = table.getColumnModel();
TableColumn tc = tcm.getColumn(0); //la prima colonna è quella che ci interessa, in questo esempio
tc.setCellRenderer(new CheckBoxTableCellRenderer());
Fatto ciò, la prima colonna dunque apparirà come una lista di JCheckBox ordinati in verticale, proprio come nello screenshot sopra. Ma c'è ancora una cosa che manca: l'editor. Infatti se proviamo a modificare il valore di una JCheckBox (quindi il selezionare/deselezionare una riga), notiamo un'anomalia: compare la scritta "true" o "false". Perché? Perchè una JTable di default implementa una DefaultCellEditor, che mostra le celle come dei JTextBox, quindi mostra "true" o "false", in modo testo. Dunque un piccolo passaggio è doveroso:
tc.setCellEditor(new DefaultCellEditor(new JCheckBox())); this.setCellSelectionEnabled(false);
Infatti (pace all'anima nostra), DefaultCellEditor prevede un costruttore con una JCheckBox. Mentre setCellSelectionEnabled() evita che si selezionino (con conseguente cambiamento del colore) le righe intere, infatti a noi interessa distinguere se una riga è selezionata o meno guardando il JCheckBox.
Ricapitolando, i due passaggi fondamentali da compiere sulla colonna sono 2: modificare il suo renderer, e modificare il suo editor . Il renderer viene eseguito solamente quando la tabella viene disegnata, mentre il comportamento (editor) viene eseguito ogni qual volta modifichiamo il valore di una JCheckBox.
E' tutto.
Alberto
Nessun commento:
Posta un commento