Проверить, когда компонент удален из JTable

У меня есть JTable, который содержит несколько панелей JPanel с использованием специального средства визуализации/редактора. JPanel прослушивает другой объект на предмет изменений. Теперь, когда я удаляю строки из JTable, JPanel все еще существует в списке слушателей в объекте, поэтому JPanel не уничтожается.

Раньше я отображал JPanel в другой JPanel, поэтому, когда объект удалялся, я мог добавить некоторый код для отмены регистрации слушателя в его методе removeNotify().

Уловка removeNotify() не работает, когда JPanel находится в JTable, потому что она постоянно удаляется и повторно добавляется в средство визуализации/редактор таблицы. Я попытался использовать addNotify(), чтобы добавить JPanel в качестве прослушивателя, но почему-то он не удаляется из списка прослушивателей. Итак, как я могу сделать это как можно более чистым?

Как я добавляю строки в таблицу:

public void fillTable()
{
    DefaultTableModel model = (DefaultTableModel) table.getModel();
    model.setRowCount(0);
    CustomPanel panel = new CustomPanel(getSomeObject());
    model.addRow(new Object[]{panel});
}

Как пользовательская панель регистрируется в качестве слушателя:

public class CustomPanel extends JPanel implements CustomObjectListener
{
    public CustomPanel(CustomObjet obj)
    {
        obj.addListener(this);
    }

    @Override
    public void CustomObjectEvent(Event evt)
    {
        handle event;
    }
}

Как выбрасывается событие:

public class CustomObject
{
    ArrayList<CustomObjectListener> listeners = new ArrayList<CustomObjectListener>();

    public CustomObject()
    {
    }

    public void addListener(CustomObjectListener listener)
    {
        listeners.add(listener);
    }

    public void removeListener(CustomObjectListener listener)
    {
        listeners.remove(listener);
    }

    public void fireEvent(Event evt)
    {
        for (CustomObjectListener listener : listeners)
        {
            listener.CustomObjectEvent(evt);
        }
    }
}

person siebz0r    schedule 25.11.2011    source источник
comment
не добавляйте в модель компоненты. Вместо этого добавьте данные, которые визуализируются/редактируются пользовательскими редакторами ячеек/-редакторами.   -  person kleopatra    schedule 26.11.2011


Ответы (2)


У меня есть JTable, который содержит несколько панелей JPanel с использованием специального средства визуализации/редактора.

У DefaultCellEditor есть метод stopCellEditing(), к которому вы можете добавить свой код.

Или, может быть, вы можете добавить в таблицу PropertyChangeListener:

public void propertyChange(PropertyChangeEvent e)
{
    //  A cell has started/stopped editing

    if ("tableCellEditor".equals(e.getPropertyName()))
    {
        if (table.isEditing())
            processEditingStarted();
        else
            processEditingStopped();
    }
}
person camickr    schedule 25.11.2011
comment
Нет, когда JPanel удаляется из JTable, JPanel необходимо удалить себя из списка слушателей объекта. Таким образом, не остается ссылок на JPanel, и GC может собирать JPanel. - person siebz0r; 25.11.2011
comment
Затем ваша CustomPanel, которую вы используете в качестве редактора, должна содержать ссылку на CustomObject. Когда вызывается stopCellEditing(), вы можете удалить прослушиватели. - person camickr; 25.11.2011

Я исправил это, создав новую модель таблицы и переопределив метод setRowCount().

public class CustomTableModel extends DefaultTableModel
{
    @Override
    public void setRowCount(int rowCount)
    {
        if (rowCount < getRowCount())
        {
            for (int i = getRowCount()-1; i >= rowCount; i--)
            {
                ((CustomPanel)getValueAt(i, 0)).removeListeners();
            }
        }
        super.setRowCount(rowCount);
    }
}
person siebz0r    schedule 28.11.2011
comment
еще раз: не смешивайте данные и область просмотра! Не храните CustomPanel в модели. Вместо этого сохраните CustomObject, заставьте модель прослушивать (свойство или пользовательскую, не имеет значения) изменения объекта и запускайте tableModelEvents по мере необходимости. - person kleopatra; 28.11.2011
comment
Прочитав этот комментарий, я как-то проснулась. Я внесу соответствующие коррективы, но не буду публиковать их, так как это не имеет отношения к заданному вопросу. - person siebz0r; 28.11.2011
comment
Для справки и, в основном, для тех, кто может просмотреть этот пост: я сделал собственный TableCellRenderer/Editor, который расширяет CustomPanel. Он берет CustomObject из модели таблицы и отображает его. Это значительно повысило производительность! Теперь вещи загружаются очень быстро, и я могу порекомендовать это всем. Клеопатра, спасибо ;-) - person siebz0r; 29.11.2011