与JTable交互,使用新行快速更新

时间:2012-03-02 00:59:03

标签: java swing jtable actionlistener

问题的简要说明。

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

以下是初步问题,更详细地解释了问题

考虑以下情况:

  1. JTable显示某些系统中当前正在运行的请求的用户信息

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

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

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

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

  6. 现在考虑系统处于压力测试状态并且频繁提交请求的情况。在我的情况下,这导致了一个错误,当有时处理用户操作的类从表模型中获取错误信息时(在一行上调用操作,但是对另一行执行操作,通常是下一行)。我相信这种情况发生是因为在动作处理过程中,由于接受了新的请求,类表模型会发生变化。

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

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

    • 创建单独的侦听器类,该类将监听表中的用户选择,并在与TableModel分开选择时立即存储来自所选行的数据。这样,动作处理类将不是从正在改变的表模型中获取数据,而是从所选行中获取数据,该行在所描述的场景期间是恒定的。 (不确定这个想法是否有效)

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

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

2 个答案:

答案 0 :(得分:4)

我不认为在表中插入行会更改选择,因此只要您在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);
            }
        });
    }
}

答案 1 :(得分:3)

  

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

这是一个启动器,用于证明选择保持不变(从某种意义上说,它始终指向相同的“实际”行:

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