简体   繁体   中英

Updating checkboxes in Jtable goes into recursion, causes stack overflow error

I have a Jtable set up in a tabbed pane that is filled with an id and checkboxes. The table looks something along the lines of this, where . are the checkboxes.

         |       VAR1        |
ID | ALL | subVar1 | subVar2 |
------------------------------
id1|  .  |    .    |    .    |

Now, I also have a TableListener attached to this table. What I would like to happen is that, whenever a user presses the ALL checkbox, all the checkboxes in that row need to be selected (ie true). This is the table listener code.

@Override
public void tableChanged(TableModelEvent e) {
    if(e.getSource() == assignedTableModel) {
        for (int i = 0; i < aTable.getRowCount(); i++) {
            boolean isAllChecked = (Boolean) aTable.getValueAt(i, 1);
            if(isAllChecked) {
                assignedTableModel.setValueAt(Boolean.TRUE, i, j);
            }
            else {
            ...
            }
        }
    }
}

Clicking the ALL checkbox causing the table to change, assignedTableModel.setValueAt(Boolean.TRUE, i, j); is called, the table is changed again and therefore calls the listener, which calls this function again.

My question, is there another way of updating the checkboxes? Or is there a way to set a base to get out of the recursion?

EDIT The rows are added dynamically. I'm wondering if adding an actionListener to the ALL checkbox as it's being added will be a solution. I'll come back with how it turns out.

EDIT2 I'd forgot to mention that the whole table is generated dynamically. That means I have no way of knowing how many columns and rows will be present, the only columns I know are ID and the ALL col. Most answers already present deal with hard coded implementations.

whenever a user presses the ALL checkbox, all the checkboxes in that row are selected

So why are you looping through all the rows in your code? The event will be generated only for the row you click and you only need to select the check marks for the columns on that row. Get rid of the looping code.

the table is changed again and therefore calls the listener, which calls this function again.

You need an if condition to identify when the check box in the first column is checked:

if (e.getType() == TableModelEvent.UPDATE)
{
    int row = e.getFirstRow();
    int column = e.getColumn();

    if (column == 0)
    {
        TableModel model = (TableModel)e.getSource();
        model.setValueAt(Boolean.true, row, 1);
                ...
    }
}

Now the change of state on the other columns will be ignored.

Based off of @camickr's response, the following piece of code seems to be doing the trick. Thanks.

    @Override
    public void tableChanged(TableModelEvent e) {
        if (e.getType() == TableModelEvent.UPDATE && e.getSource() == assignedTableModel)
        {
            int row = e.getFirstRow();
            int column = e.getColumn();

            if (column == 1)
            {
                DefaultTableModel model = (DefaultTableModel) e.getSource();
                for(int i=2 ; i<model.getColumnCount() ; i++) {
                    if((boolean) model.getValueAt(row, 1))
                        model.setValueAt(Boolean.TRUE, row, i);
                    else
                        model.setValueAt(Boolean.FALSE, row, i);
                }
            }
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM