Reputation: 5316
I am using a custom CellEditor in a column
UPDATE: added a SSCCE
public class TestJFrame extends javax.swing.JFrame {
public TestJFrame() {
initComponents();
jTable1.getTableHeader().addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
final JTableHeader tableHeader = (JTableHeader) e.getSource();
final JTable table = tableHeader.getTable();
final int column = tableHeader.columnAtPoint(e.getPoint());
if (column == 1) {
TableCellEditor editor = table.getColumnModel()
.getColumn(column)
.getCellEditor();
for (int row = 0; row < table.getModel().getRowCount(); row++) {
if (table.getModel().isCellEditable(row, column)) {
editor.getTableCellEditorComponent(table, (e.getButton() == MouseEvent.BUTTON1),
false,
row,
column);
tableHeader.getTable().setValueAt((e.getButton() == MouseEvent.BUTTON1),
row,
column);
}
}
}
}
});
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null},
{null, null},
{null, null}
},
new String [] {
"name", "click me"
}
) {
Class[] types = new Class [] {
java.lang.String.class, java.lang.Boolean.class
};
boolean[] canEdit = new boolean [] {
false, true
};
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
jScrollPane1.setViewportView(jTable1);
if (jTable1.getColumnModel().getColumnCount() > 0) {
jTable1.getColumnModel().getColumn(0).setResizable(false);
jTable1.getColumnModel().getColumn(0).setPreferredWidth(100);
jTable1.getColumnModel().getColumn(1).setCellEditor(new SwitchCellEditor(new EnableCheckbox(jTable1), jTable1));
}
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 91, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(TestJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(TestJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(TestJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(TestJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestJFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTable1;
// End of variables declaration
private static class EnableCheckbox extends JCheckBox {
public EnableCheckbox(final JTable table) {
addItemListener(new EnableCheckboxItemListenerImpl(table));
}
private final class EnableCheckboxItemListenerImpl implements ItemListener {
private final JTable _table;
public EnableCheckboxItemListenerImpl(final JTable table) {
_table = table;
}
@Override
public void itemStateChanged(ItemEvent e) {
final JCheckBox checkBox = (JCheckBox) e.getSource();
final int selectedRow = _table.rowAtPoint(checkBox.getLocation());
final int selectedColumn = _table.columnAtPoint(checkBox.getLocation());
// doStuff
}
}
}
private class SwitchCellEditor extends DefaultCellEditor {
private final JTable _table;
private final JCheckBox _checkBox;
public SwitchCellEditor(final JCheckBox checkBox, final JTable table) {
super(checkBox);
_checkBox = checkBox;
_table = table;
}
@Override
public final Component getTableCellEditorComponent(
final JTable table,
final Object value,
final boolean isSelected,
final int row,
final int column) {
Rectangle r = _table.getCellRect(row, column, false);
if (_checkBox != null) {
_checkBox.setLocation(new Point(r.x, r.y + r.height));
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
}
The itemStateChanged method is only called on the first iteration step, but not on the following iteration steps.
Why is it behaving like that and how can I make it call itemStateChanged on each iteration step?
Upvotes: 1
Views: 67
Reputation: 205825
Your implementation … does not call
itemStateChanged
for each editor in each row.
Exactly. JTable
uses the flyweight pattern for editors, updating the TableModel
only after the editor concludes. If you want to see the editor's state change, you can either
Use the approach in the example cited here, in which the editor listens to the JCheckBox
used by the corresponding renderer.
Add a CellEditorListener
, mentioned here.
Upvotes: 1