【问题标题】:Interacting with JTable which is rapidly updated with new rows与快速更新新行的 JTable 交互
【发布时间】:2012-03-02 00:59:03
【问题描述】:

问题的简要描述。

假设我们有 JTable 和用户以某种方式与之交互。这个表的 TableModel 是不断变化的。如何确保当用户尝试通过引用某个常量列和当前选定的行(通过他从 JTable 获得的 rowIndex)从表中获取一些信息时,当 TableModel 更改并且他从 JTable 获得的 rowIndex 时,他不会陷入这种情况不再对应 TableModel 中的相同值。

以下是更详细地解释问题的初始问题

考虑以下情况:

  1. 有一个 JTable 可以显示一些系统中当前正在运行的请求的用户信息

  2. 当新请求进入系统时,新行被添加到表中

  3. 用户可以通过右键单击一行(表中使用单行选择模型)并从菜单中选择选项(如:中止、推迟、重试等)与表进行交互

  4. 有一个单独的类实现 ActionListener 接口(监听表)并处理所有用户交互

  5. 当用户对表执行某些操作时,此类检查当前选定的行并为用户的操作分配一些值(基本上它获取选定行的索引,然后调用 tableModel.getValueAt(indexOfSelectedRow, someValuableDataColumnIndex))

现在考虑系统处于压力测试中并且请求不断以高频率提交的情况。在我的情况下,这会导致一个错误,当有时处理用户操作的类从表模型中获取错误信息时(在一行上调用了操作,但对另一行执行了操作,通常是下一行)。我相信会发生这种情况,因为在某些初始化操作期间,处理类表模型由于接受了新请求而发生了更改。

问题是,如何解决这个问题。我正在考虑两种方法:

  • 在我的用户操作处理类中使用诸如 invokeAndWait() 之类的东西进行初始化(不喜欢这个想法,因为 imo 会导致其他不可预知的错误)

  • 创建单独的侦听器类,该类将侦听表中的用户选择,并在从 TableModel 中单独选择后立即存储选定行中的数据。这样,动作处理类将不会从正在更改的表模型中获取数据,而是从所选行中获取数据,这在所描述的场景中是恒定的。 (不确定这个想法是否可行)

请评论我的想法,并提出你的建议。

很抱歉这里没有任何代码,但是原始代码会占用太多空间,并且模型示例不是在这里可以轻松完成的。

【问题讨论】:

  • 在考虑了我的第二个想法后,我意识到它行不通。它具有相同的两个步骤:1)获取选定的行索引 2)从表模型中获取具有该索引的行的信息。在这两个步骤之间出现在表格中的任何新行都会搞砸。
  • 有多少线程访问TableModel?如果不止一个,它们如何同步访问?另请参阅此sscce 和此Q&A
  • @trashgod TableModel 仅由一个线程访问。也感谢链接,有趣的信息。目前无法从中找出任何有用的信息,但肯定会更深入地研究它。
  • 您可以使用引用的方法之一来验证仅 EDT 对模型的访问。是否曾经删除过行?
  • 听起来您的代码可能有问题:行选择保持在同一“真实”行上。也就是说,如果在上面插入一行,绝对索引会增加,但仍然指向与之前相同的对象。

标签: java swing jtable actionlistener


【解决方案1】:

我不认为在表中插入行会改变选择,因此只要您在 EDT 上更新 TableModel,当用户显示弹出窗口并从弹出窗口中选择和操作时,所选行仍然相同。

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class TestJTableInsert {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                final DefaultTableModel model = new DefaultTableModel(0, 1);
                new Timer(500, new ActionListener() {
                    private final Random random = new Random();
                    private int data = 1;

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        model.insertRow(random.nextInt(model.getRowCount() + 1),
                                new Object[] { data++ });
                    }
                }).start();

                final JTable table = new JTable(model);
                JPopupMenu popup = new JPopupMenu();
                popup.add(new AbstractAction("Which row is this?") {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JOptionPane.showMessageDialog(table,
                                "This is row " + table.getValueAt(table.getSelectedRow(), 0));
                    }
                });
                table.setComponentPopupMenu(popup);
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.getContentPane().add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

【讨论】:

  • 该死,你打败了我——因为我必须证明自己是人类(通过阅读几乎无法分辨的验证码:)
【解决方案2】:

模型示例不是在这里可以轻松完成的。

这是一个证明选择保持不变的开始(从某种意义上说,它总是指向相同的“真实”行:

final DefaultTableModel model = new DefaultTableModel(0, 1);
for (int i = 0; i < 50; i++) {
    model.addRow(new Object[] {i});
};

final JXTable table = new JXTable(model);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setRowSelectionInterval(25, 25);
Action l = new AbstractAction("random insert") {
    Random random = new Random();
    @Override
    public void actionPerformed(ActionEvent e) {
        int row = random.nextInt(model.getRowCount());
        model.insertRow(row, new Object[] {"inserted at: " + row});
        table.scrollRowToVisible(table.getSelectedRow());
    }

};
new Timer(100, l).start();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 2015-01-24
    • 1970-01-01
    • 2013-12-19
    • 1970-01-01
    相关资源
    最近更新 更多