Удалить AbstractAction из jtable - PullRequest
       20

Удалить AbstractAction из jtable

1 голос
/ 25 декабря 2011

Хорошо.У меня большой проект, в котором при запуске создается jtable, который никогда не перестраивается.Модель таблицы обновляется, а таблица перерисовывается на основе различных действий пользователя.

Я добавил пользовательский класс TableCellListener для реагирования на изменения ячейки вместе с AbstractAction.Вот код, который выполняется при первом заполнении таблицы данными.(Без проверки 'firstLoad' каждый раз при перерисовке таблицы прикреплялось несколько действий).

if(firstLoad) {
    AbstractAction action = new AbstractAction()
    {
        public void actionPerformed(ActionEvent e)
        {
            TableCellListener tcl = (TableCellListener)e.getSource();


                    sayIt("Row:" + tcl.getRow()+" Column:" + tcl.getColumn()+
                        " Old:" + tcl.getOldValue()+" New:" + tcl.getNewValue());

        }
    };

    firstLoad = false;
    TableCellListener tcl = new TableCellListener(table2, action);
}

TableCellListener - пользовательский слушатель, опубликованный здесь Робом Кэмиком и 'sayIt'bit - это мой собственный код отладки.

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

Я вполне уверен, что вызов типа removePropertyChangeListener () сделает это, но ожидает слушателя в качестве аргумента, и я не уверен, как его найти.

Ответы [ 3 ]

4 голосов
/ 25 декабря 2011

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

Следует сохранить текущее значение, когда вы начинаете редактирование, и генерировать событие, когда вы прекращаете редактирование. Когда вы меняете TableModel, вы не должны редактировать никакие ячейки. Поэтому, когда вы генерируете следующее событие, которое подразумевает, что вы выбрали и начали редактирование в другой ячейке, в этом случае у вас должно быть текущее значение для новой модели. У меня работает нормально:

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.io.*;
import java.net.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableCellListenerTest2
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI()
    {
        final JTable table = new JTable( TableCellListenerTest2.createModel());
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);

        Action action = new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                TableCellListener tcl = (TableCellListener)e.getSource();
                System.out.println( tcl.getOldValue() + " : " + tcl.getNewValue() );
            }
        };

        TableCellListener tcl = new TableCellListener(table, action);

        JButton button = new JButton("Reset Model");
        button.addActionListener( new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                table.setModel( TableCellListenerTest2.createModel() );
            }
        });

        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Table Cell Listener");
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( scrollPane );
        frame.add(button, BorderLayout.SOUTH);
        frame.setSize(400, 160);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

    public static TableModel createModel()
    {
        Random random = new Random();

        DefaultTableModel model = new DefaultTableModel(10, 2);

        for (int i = 0; i < model.getRowCount(); i++)
            model.setValueAt("" + random.nextInt(100), i, 0);

        return model;
    }
}

Опубликуйте свой SSCCE, если вам нужна дополнительная помощь.

1 голос
/ 25 декабря 2011

Почему бы просто не сделать TableCellListener, tcl, полем класса и удалить его, если модель перестраивается, а затем пересобрать слушатель и заново добавить его.

0 голосов
/ 25 декабря 2011

Просто запомните экземпляр TableCellListener в переменной экземпляра:

// side effect: the tcl is added as PropertyChangeListener to the table 
// (bad design, IMHO)
this.tcl = new TableCellListener(table2, action);

// when the table data changes: 
if (this.tcl != null) {
    table2.removePropertyChangeListener(this.tcl);
}
this.tcl = new TableCellListener(table2, action);
...