【问题标题】:Remove AbstractAction from jtable从 jtable 中删除 AbstractAction
【发布时间】:2011-12-24 22:31:22
【问题描述】:

好的。我有一个大型项目,其中在启动时创建了一个特定的 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 是 Rob Camick here 发布的自定义侦听器,“sayIt”位是我自己的调试代码。

这一切都很好,但我想在每次重建表时完全删除监听器并再次添加它,因为它正在“记住”最后一个选定单元格的值,现在由于表数据无效是新的。

我相当肯定 'removePropertyChangeListener()' 类型调用会做到这一点,但它希望侦听器作为参数,我不知道如何找到它。

【问题讨论】:

  • 正如@camickr 已经提到的:您没有显示的代码有问题,是时候进行 sscce 了
  • 是的。我现在正在解决问题。我还使用选择侦听器自动选择单元格内容进行编辑(使用户不必不断双击),我认为这可能是问题,因为 camickr 的测试代码确实按预期工作。

标签: java swing jtable abstraction tablemodel


【解决方案1】:

因为它正在“记住”最后选择的单元格中的值,现在由于表格数据是新的,因此该值无效。

它应该在您开始编辑时保存当前值,并在您停止编辑时生成事件。当您更改 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。

【讨论】:

  • 不确定 SSCCE 是什么。我很抱歉我有点新手。但是,是的,您的代码确实按预期工作。 “当您更改 TableModel 时,您不应该编辑任何单元格。” ...这可能是我认为的问题。我也使用了一个选择监听器(如上所述),所以我很可能需要在重建表之前取消选择行/列,但到目前为止,'table2.getSelectionModel().clearSelection()' 编译但只是破坏了一切。将继续排除故障。感谢您的提示和测试代码。
  • 我发布了一个 SSCCE。您可以搜索网络以了解更多详细信息。我也不明白为什么 SelectionLIsener 会导致问题。要测试您的理论,您所要做的就是修改我的代码以添加一个 SelectionListener。
  • 似乎我在选择模型和列模型上有一个监听器。一旦我删除了列模型侦听器,然后,在重新填充表之前,取消编辑并执行 clearSelection() 一切正常。感谢您的帮助并为我指明正确的方向。 (以及 SSCCE 提示)。
【解决方案2】:

为什么不简单地将TableCellListener,tcl,一个类字段,如果模型被重建,将其删除,然后重新构建监听器并重新添加它。

【讨论】:

  • 气垫船:感谢您的快速回复。我对此有点新手,所以我会尝试一下,看看它是如何进行的。谢谢。
【解决方案3】:

只需记住实例变量中的 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);

【讨论】:

  • 谢谢 JB。试过了,但它不喜欢'this.tcl'。 tcl 需要先在某个地方声明吗?我会看看我能想出什么。
  • 如果是this.tcl,说明tcl确实是实例变量,必须在实例中声明。见docs.oracle.com/javase/tutorial/java/javaOO/variables.html
  • -1 没有必要删除监听器,OP 没有显示的代码有问题(正如@camickr 已经提到的那样)而且设计也没有什么不好:整点那个助手类在编辑之前自动跟踪值(这意味着......好吧......听表的编辑状态的变化)
  • 我的“糟糕设计”评论是关于构造函数有副作用的事实,并让尚未完全构造的实例泄漏。仅调用“new TableCellListener(...)”来创建侦听器并将其附加到表上,这是糟糕的设计,恕我直言。
  • @kleopatra - 是的,事实证明,如上所述,程序的其他区域存在一些代码问题。在跟踪它们之后,更改侦听器按设计完美运行​​。感谢大家的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 2012-01-02
  • 1970-01-01
  • 2014-08-28
相关资源
最近更新 更多