Question

I have a JTable that holds several JPanels using a custom renderer/editor. The JPanel listens to another object for changes. Now when I remove the rows from the JTable the JPanel still exists in the listener list in the object so the JPanel doesn't get destroyed.

Previously I displayed the JPanel in another JPanel so when the object got removed I could add some code to unregister the listener in its removeNotify() method.

The removeNotify() trick doesn't work when the JPanel is in a JTable because it is constantly removed and re-added to the table's renderer/editor. I tried using addNotify() to add the JPanel as a listener, but somehow it doesn't get removed from the listener list. So how can I do this as clean as possible?

How I add rows to the table:

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

How the custom panel registers as a listener:

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

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

How the event is thrown:

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);
        }
    }
}
Was it helpful?

Solution 2

I fixed it by creating a new TableModel and overriding the setRowCount() method.

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

OTHER TIPS

I have a JTable that holds several JPanels using a custom renderer/editor.

The DefaultCellEditor has a stopCellEditing() method you should be able to add your code to.

Or maybe you can add a PropertyChangeListener to the table:

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

    if ("tableCellEditor".equals(e.getPropertyName()))
    {
        if (table.isEditing())
            processEditingStarted();
        else
            processEditingStopped();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top