Java: 单击另一个复选框时自动更新 JTable 中的复选框

Java: Automatically Update a Checkbox in JTable when Another Checkbox is Clicked

我希望在单击 EventYearMatchingWindow 中 JTable 中的复选框时自动选中 EventYearMatchingUnitPanel class 中 JTable 中的每个复选框。

单击第一张图片中的 "unit 9" 复选框 (https://ibb.co/fsqtrQ) should automatically select all 5 checkboxes in the second picture (https://ibb.co/f8ja5k)

我使用 TabelModelListener 中的 tableChanged() 方法来检测复选框是否被单击。当我单击复选框时,它会更改其他复选框的值(从 Boolean.FALSE 到 Boolean.TRUE),但复选框不会更新(不会实际显示复选标记)。

//for the first JTable
public void tableChanged(TableModelEvent e){
    int row = e.getFirstRow();
    int column = e.getColumn();
    TableModel model = (TableModel)e.getSource();
    String columnName = model.getColumnName(column);
    Object thatValue = model.getValueAt(row, column);
    data[row][column] = thatValue;
    for(int i = 0; i < unitPanels[row].getNumRows(); i++){
        unitPanels[row].setToSelectedState(i);
    }
} 

//for the second JTable
public void setToSelectedState(int row){    
    data[row][0] = Boolean.TRUE;
    model.fireTableCellUpdated(row, 0);
}

这是代码的大图:

public class EventYearMatchingWindow extends JFrame implements 
TableModelListener
{
    private boolean columnHeaderClicked;
    private ArrayList<Category> categories;
    private JPanel mainPanel, listPanel, buttonPanel;
    private ArrayList<Item> selectedItems;
    private EventYearMatchingItemChoosing[] unitPanels;
    Object data[][];
    public EventYearMatchingWindow(ArrayList<Category> c){
        ...
        String[] columnNames = {"Include?", ""};   
        data = new Object[6][2];
        for(int i = 0; i < 6; i++){
            data[i][0] = Boolean.FALSE;
            data[i][1] = "Unit " + (i+8);
        }
        DefaultTableModel model = new DefaultTableModel(data, columnNames) {
            private static final long serialVersionUID = 1L;
            @Override
            public Class getColumnClass(int columnIndex) {
                if (columnIndex == 0){
                    return Boolean.class;
                }
                return super.getColumnClass(columnIndex);
            }
        };

        JTable table = new JTable(model);
        table.getModel().addTableModelListener(this);
        table.addMouseListener(new java.awt.event.MouseAdapter() {
        ....
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                int row = table.rowAtPoint(evt.getPoint());
                int col = table.columnAtPoint(evt.getPoint());
                if (row == -1 && col >= 0){
                    columnHeaderClicked = true;
                }
                if (row >= 0 && col == 1 && !columnHeaderClicked) {
                    mainPanel.removeAll();

                    System.out.println(unitPanels[row].getData()[0][0]);
                    unitPanels[row].revalidate();
                    unitPanels[row].repaint();

                    mainPanel.add(unitPanels[row]);
                    JPanel nButtonPanel = new JPanel();
                    Button back = new Button("Back");
                    nButtonPanel.add(back);
                    back.addActionListener(new ActionListener(){
                        public void actionPerformed(ActionEvent e){
                            mainPanel.removeAll();
                            mainPanel.add(listPanel);
                            mainPanel.add(buttonPanel);
                            mainPanel.revalidate();
                            repaint();
                        }
                    });
                    mainPanel.add(nButtonPanel);
                    mainPanel.revalidate();
                    repaint();
                }
            }
        });   
    }
    public void tableChanged(TableModelEvent e){
        int row = e.getFirstRow();
        int column = e.getColumn();
        TableModel model = (TableModel)e.getSource();
        String columnName = model.getColumnName(column);
        Object thatValue = model.getValueAt(row, column);
        data[row][column] = thatValue;
        for(int i = 0; i < unitPanels[row].getNumRows(); i++){
            unitPanels[row].setToSelectedState(i);
        }
    } 
}

并且:

public class EventYearMatchingItemChoosing extends JPanel implements TableModelListener
{
    Category category;
    private boolean columnHeaderClicked;
    private int size;
    private ArrayList<Item> items;
    private Object[][] data;
    DefaultTableModel model;
    public EventYearMatchingItemChoosing(String s, ArrayList<Category> c){
        ...
        String[] columnNames = {"Include?", "Event", "Year"};   
        data = new Object[size][3]
        for(int i = 0; i < category.getItems().size(); i++){ 
            if(!category.getItems().get(i).getEvent().equals("") && !category.getItems().get(i).getYear().equals("")){
                data[i][0] = Boolean.FALSE;
                data[i][1] = category.getItems().get(i).getEvent();            
                data[i][2] = category.getItems().get(i).getYear();   
            }
        }    

        model = new DefaultTableModel(data, columnNames) {   
            private static final long serialVersionUID = 1L;   
            @Override
            public Class getColumnClass(int columnIndex) {
                if (columnIndex == 0){
                    return Boolean.class;
                }
                return super.getColumnClass(columnIndex);
            }    
        };
        JTable table = new JTable(model);
        table.getModel().addTableModelListener(this);
        ...
    }
    ...
    public void tableChanged(TableModelEvent e){
        int row = e.getFirstRow();
        int column = e.getColumn();
        TableModel model = (TableModel)e.getSource();
        String columnName = model.getColumnName(column);
        Object thatValue = model.getValueAt(row, column);
        data[row][column] = thatValue;
    }
    public void setToSelectedState(int row){    
        data[row][0] = Boolean.TRUE;
        model.fireTableCellUpdated(row, 0);
    }
}

but the checkboxes don't update (don't physically show the checkmarks).

data[row][0] = Boolean.TRUE;

永远不要访问数据数组。数据 Array 用于创建 DefaultTableModel,然后将数据从 Array 复制到 DefaultTableModel 使用的数据结构(恰好是 Vector of Vectors)。

最终结果是 TableModel 中的数据永远不会改变。

代码应该是:

model.setValueAt(Boolean.TRUE, row, 0);