2011-12-24 2 views
1

Ok. У меня большой проект, где конкретная jtable создается при запуске и никогда не восстанавливается. Модель таблицы обновляется, а таблица перерисовывается на основе различных действий пользователя.Удалить AbstractAction от 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 обычай слушатель отправил here Роб Camick и бит «sayIt» мой собственный код отладки.

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

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

+0

как @camickr уже упоминалось: что-то не так с кодом, который вы не показываете, время для sscce – kleopatra

+0

Да. Сейчас я начинаю стрелять. Я также использую прослушиватель выбора для автоматического выбора содержимого ячеек для редактирования (он не позволяет пользователю дважды кликать), и я думаю, что это может быть проблемой, поскольку тестовый код Camickr работает так, как ожидалось. – jeff

ответ

4

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

Он должен сохранить текущее значение при запуске редактирования и генерации события при прекращении редактирования. Когда вы меняете 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, если вам нужна дополнительная помощь.

+0

Не знаете, что такое SSCCE. Приношу свои извинения за то, что я немного новичок. Но да, ваш код работает так, как ожидалось. «Когда вы меняете TableModel, вы не должны редактировать какую-либо ячейку». ... это может быть проблема, о которой я думаю. Я использую прослушиватель выбора (как упоминалось выше), так что, скорее всего, мне нужно будет отменить выбор строк/столбцов до того, как таблица будет перестроена, но до сих пор «table2.getSelectionModel(). ClearSelection()» компилирует, а просто разбивает все. Будет продолжаться устранение неполадок. Спасибо за подсказку и тестовый код. – jeff

+0

Я отправил SSCCE. Вы можете искать в Интернете, чтобы узнать больше. Я не понимаю, почему SelectionLIstener также вызовет проблему. Чтобы проверить свою теорию, все, что вам нужно сделать, это изменить мой код, чтобы добавить SelectionListener. – camickr

+0

Кажется, у меня был слушатель по модели выбора и модели столбца. Как только я удалил прослушиватель модели столбца, а затем, как раз перед повторным заполнением таблицы, отменил редактирование и сделал clearSelection(), все это работало так, как должно. Спасибо за помощь и укажут меня в правильном направлении. (И совет SSCCE). – jeff

1

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

+0

Судно на воздушной подушке: спасибо за быстрый ответ. Я немного новичок в этом, поэтому я немного экспериментирую и посмотрю, как это происходит. Благодарю. – jeff

0

Просто помните экземпляр 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); 
+0

Спасибо JB. Пробовал, но ему не нравится «this.tcl». tcl нужно сначала объявить? Я посмотрю, что я могу понять. – jeff

+0

Если это this.tcl, это означает, что tcl действительно является переменной экземпляра, которая должна быть объявлена ​​в экземпляре. См. Http://docs.oracle.com/javase/tutorial/java/javaOO/variables.html –

+0

-1 нет необходимости удалять слушателя, что-то не так с кодом, который OP не показывает (поскольку @camickr уже) И ничего плохого в дизайне: целая точка этого вспомогательного класса _is_ для автоматического отслеживания значения перед редактированием (что подразумевает ... хорошо ... прослушивание изменения состояния редактирования таблицы) – kleopatra

Смежные вопросы