Mateusz Fryc
Mateusz Fryc

Reputation: 73

Is modifying model of JTable allowed while processing TableModelEvent?

I am wondering how to implement such behavior, which would let me to delete row from JTable when value in particular column of this row changes to some fixed value.

I tried to do it using TableModelListener but without intended effect. My problem is connected with the fact that, when I modify model while processing UPDATE TableModelEvent then I condemn myself to deal with inconsistency between possibly modified model (Source of event) with the Event itself. In other words events could have been generated based on different state of the model of table.

void onTableChanged(TableModelEvent tableModelEvent)
{
    MyTableModel model = (MyTableModel)e.getSource();
    if ( e.getType() == TableModelEvent.UPDATE){
        MyObject myObject = (MyObject)model.getValueAt(e.getFirstRow(), e.getColumn());
        if ( myObject.getSomeProperty().equals("DELETE ME")){
          model.removeRow(e.getFirstRow()); // does it look like asking for troubles?
        }            
    }
}

and now imagine, we have a method which let us update several rows at once.

class MyObject {
    private String someProperty;

    //...getters/setters
}

class MyTableModel extends AbstractTableModel {
    private static int SOME_PROPERTY_COL = 1;     
    private final List<MyObject> data;

    public MyTableModel(List<MyObject> data)
    {
        this.data = data;
    }

    //...

    void update(int[] modelIndices, String newSomePropertValue)
    {
        for (int i = 0; i < modelIndices.length; i++){
            data[modelIndices[i]].setSomeProperty(newSomePropertyValue);
            fireCellUpdated(modelIndices[i], SOME_PROPERTY_COL);
        }
    }
}

There is inconsistency in such implementation between rowIndex, colIndex, in TableModelEvent vs state of model at the time of second, and later events received as a result of invoking update(int[], String) method on MyTableModel object.

I believe the problems comes from the fact that, I try to modify source of events while receiving events generated basing on some particular state of this source, but would not that be an issue as well, if e.g whatever event indicating change in the mode was interleaved with model modification, and some other event which was generated based on old state of model?

What I would like to achieve ultimately is implementation which would let me move row from one table to another table basing on value in some column in a table.

So Imagine one of the cell is a combo box, with 2 values, and we have a two tables, when value in a cell changes to table1 then row is transferred from current table to table1. I thought that using TableModelListener would be proper solution, but I can see that modifying model within this method is not a good idea, isn't it?

Upvotes: 0

Views: 65

Answers (1)

camickr
camickr

Reputation: 324157

model.removeRow(e.getFirstRow()); // does it look like asking for troubles?

Wrap the code in a SwingUtilities.invokeLater(...).

Now the code will be added to the end of the Event Dispatch Thread (EDT) so the table processing and table model listener processing can finish normally before the row deletion is done.

SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        model.removeRow(e.getFirstRow());
    }
});

Also, in your update() method you will need to update the data of the model in reverse model row order. This way when you do the delete of the rows there is no issue with the indexes being incorrect.

Upvotes: 2

Related Questions