Java 在JTable中侦听JCheckBox中的更改

Java 在JTable中侦听JCheckBox中的更改,java,swing,jtable,jcheckbox,Java,Swing,Jtable,Jcheckbox,如何在一个JTable列中侦听包含JCheckBox的更改?我想知道用户何时选择/取消选择该复选框。列的类被设置为boolean,因此它会自动呈现为JCheckBox。我认为您需要的是通过使用。也可以使用自定义编辑器,但我认为TableModelListener是最简单的方法。重写的tableChanged方法可能如下所示 @Override public void tableChanged(TableModelEvent e) { int row = e.getFirstRow();

如何在一个JTable列中侦听包含JCheckBox的更改?我想知道用户何时选择/取消选择该复选框。列的类被设置为boolean,因此它会自动呈现为JCheckBox。

我认为您需要的是通过使用。也可以使用自定义编辑器,但我认为
TableModelListener
是最简单的方法。重写的
tableChanged
方法可能如下所示

@Override
public void tableChanged(TableModelEvent e) {
    int row = e.getFirstRow();
    int column = e.getColumn();
    if (column == BOOLEAN_COLUMN) {
        TableModel model = (TableModel) e.getSource();
        String columnName = model.getColumnName(column);
        Boolean checked = (Boolean) model.getValueAt(row, column);
        if (checked) {
            System.out.println(columnName + ": " + true);
        } else {
            System.out.println(columnName + ": " + false);
        }
    }
}

下面是一个完整的运行示例

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class TestTableModelListener {
    private static final int BOOLEAN_COLUMN = 2;

    public TestTableModelListener() {
        JTable table = createTable();
        table.getModel().addTableModelListener(new CheckBoxModelListener());

        JFrame frame = new JFrame();
        frame.add(new JScrollPane(table));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private JTable createTable() {
        String[] cols = {"COL", "COL", "COL"};
        Object[][] data = {{"Hello", "Hello", false}, {"Hello", "Hello", false}};
        DefaultTableModel model = new DefaultTableModel(data, cols) {
            @Override
            public Class getColumnClass(int column) {
                return column == BOOLEAN_COLUMN ? Boolean.class : String.class;
            }
        };
        JTable table = new JTable(model);
        return table;
    }

    public class CheckBoxModelListener implements TableModelListener {

        public void tableChanged(TableModelEvent e) {
            int row = e.getFirstRow();
            int column = e.getColumn();
            if (column == BOOLEAN_COLUMN) {
                TableModel model = (TableModel) e.getSource();
                String columnName = model.getColumnName(column);
                Boolean checked = (Boolean) model.getValueAt(row, column);
                if (checked) {
                    System.out.println(columnName + ": " + true);
                } else {
                    System.out.println(columnName + ": " + false);
                }
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TestTableModelListener();
            }
        });
    }
}

多亏了mKorbel的评论,我为表模型重新编写了setValueAt方法:

public void setValueAt(Object value, int row, int col) {
    super.setValueAt(value, row, col);
    if (col == 4) {
        if ((Boolean) this.getValueAt(row, col) == true) {
            //code goes here
        }
        else if ((Boolean) this.getValueAt(row, col) == false) {
            //code goes here
        }
    }   
}
现在,代码只在单元格中的值实际更改时执行,这就是我想要的

现在,代码只在单元格中的值实际更改时执行,这就是我想要的


查看专门为这种情况设计的。

另一种方法是在JTable中创建一个MouseClicked事件,当您在JTable中的某个位置单击时会触发该事件。在事件内部,我们保存行数和列数。然后我们假设在Jtable的第4列和第5列中有两个复选框。例如,如果我们按下第2行和第4列,我们在JTable中标记复选框,并使用更新sql语句将checbox的布尔值保存在数据库中

private void RegistroFacturaTableMouseClicked(java.awt.event.MouseEvent evt) {                                                  
        int filaSeleccionada = RegistroFacturaTable.rowAtPoint(evt.getPoint());
        int columnaSeleccionada = RegistroFacturaTable.columnAtPoint(evt.getPoint());
        if(evt.getClickCount() == 2){
            int idRegistroFactura = (int) RegistroFacturaTable.getValueAt(filaSeleccionada, 0);
            setVisible(false);
            new VerCobros(this, idRegistroFactura, contrato);
        } else if (columnaSeleccionada == 4 ){
            int idRegistroFactura = (int) RegistroFacturaTable.getValueAt(filaSeleccionada, 0);
            boolean agua = (boolean) RegistroFacturaTable.getValueAt(filaSeleccionada, 4);
            DataBase.updateRegistroFacturaSetAguaWhereIdRegistroFactura(agua, idRegistroFactura); 
        } else if ( columnaSeleccionada == 5 ){
           int idRegistroFactura = (int) RegistroFacturaTable.getValueAt(filaSeleccionada, 0);
           boolean luz = (boolean) RegistroFacturaTable.getValueAt(filaSeleccionada, 5);
           DataBase.updateRegistroFacturaSetLuzWhereIdRegistroFactura(luz, idRegistroFactura);
        }      
    }   

tableChanged方法的问题在于,它没有告诉我布尔值何时实际更改,这就是我需要捕获的。什么意思?它没有告诉你布尔值何时更改?我不确定我是否听懂了。这似乎正是侦听器所做的,当值更改时,它会告诉您。+1,结果应该是侦听生产代码的setValueAt peeskillet:尝试在不更改任何内容的情况下将光标移入和移出单元格。您将看到仍然会有输出。这是因为“表更改”不仅捕获数据中的更改,还捕获单元格中的任何移动。@user3245747我不确定您所说的行为,我不明白。你的说法也不正确。正如教程“表模型可以有一组监听器,在表数据更改时会通知这些监听器”中所述,尽管这可能对您有用,但它并没有回答用户是否选择或取消选择复选框的问题。方法setValueAt也可以在没有实际用户交互的情况下以编程方式调用