Разрешено ли изменение модели JTable при обработке TableModelEvent? - PullRequest
0 голосов
/ 31 августа 2018

Мне интересно, как реализовать такое поведение, которое позволило бы мне удалить строку из JTable, когда значение в определенном столбце этой строки изменяется на некоторое фиксированное значение.

Я пытался сделать это с помощью TableModelListener, но без ожидаемого эффекта. Моя проблема связана с тем, что, когда я изменяю модель во время обработки UPDATE TableModelEvent, я обрекаю себя на то, чтобы иметь дело с несоответствием между возможно измененной моделью (источником события) и самим событием. Другими словами, события могли генерироваться на основе другого состояния модели таблицы.

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?
        }            
    }
}

и теперь представьте, у нас есть метод, который позволяет обновлять несколько строк одновременно.

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);
        }
    }
}

В такой реализации существует несоответствие между rowIndex, colIndex, в TableModelEvent и состоянием модели во время секунды и последующими событиями, полученными в результате вызова метода update (int [], String) для объекта MyTableModel.

Я полагаю, что проблема возникает из-за того, что я пытаюсь изменить источник событий при получении событий, сгенерированных на основе определенного состояния этого источника, но это также не будет проблемой, если, например, любое событие, указывающее на изменение в режим был чередован с модификацией модели и каким-либо другим событием, которое было сгенерировано на основе старого состояния модели?

В конечном итоге я бы хотел добиться реализации, которая позволила бы мне перемещать строки из одной таблицы в другую на основе значения в некотором столбце таблицы.

Итак, представьте, что одна из ячеек является комбинированным полем с двумя значениями, и у нас есть две таблицы, когда значение в ячейке изменяется на table1, а затем строка переносится из текущей таблицы в table1. Я думал, что использование TableModelListener было бы правильным решением, но я вижу, что изменение модели в этом методе не очень хорошая идея, не так ли?

1 Ответ

0 голосов
/ 31 августа 2018
model.removeRow(e.getFirstRow()); // does it look like asking for troubles?

Оберните код в SwingUtilities.invokeLater(...).

Теперь код будет добавлен в конец потока диспетчеризации событий (EDT), чтобы обработка таблицы и обработка прослушивателя модели таблицы могли нормально завершиться до того, как будет выполнено удаление строки.

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

Кроме того, в вашем методе update() вам нужно будет обновить данные модели в обратном порядке строк модели. Таким образом, при удалении строк не возникает проблем с неверными индексами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...