【问题标题】:Java update jtable row from another threadJava 从另一个线程更新 jtable 行
【发布时间】:2012-08-09 20:29:11
【问题描述】:

我有一个多线程程序,我正在尝试使用 JTable 来查看每个线程的进度。每个线程都是一行JTable。我已经发布了我现在拥有的简化且相关的代码。每次我按下开始时,都会启动一个新线程并将该行添加到 JTable 中。但是如何从正在运行的线程中更新属于该线程的行中的“第 2 列”?

这就是我所拥有的

JTable table = new JTable(new DefaultTableModel(new Object[]{"Thread Name", "Progress"}, 0));

btnBegin.addActionListener(new ActionListener()
{
  public void actionPerformed(ActionEvent arg0)
  {
    Thread newThread = new Thread(new MyThreadClass(country, category));
    newThread.start();
    DefaultTableModel model = (DefaultTableModel) table.getModel();
    model.addRow(new Object[]{"Thread " + threadNumber, "Column 2"});
  }
});

【问题讨论】:

  • 您想在添加后还是在添加时更新列?你想用这个专栏做什么?

标签: java multithreading swing jtable event-dispatching


【解决方案1】:

如果您可以将字段 tableModel 添加到 MyThreadClass(字段+构造函数参数),则可以从此类中调用 @sedran 提到的代码。

例子:

public class T {

static int threadNumber = 0;

public static void main(String[] args) throws Exception {

    final JTable table = new JTable(new DefaultTableModel(new Object[] { "Thread Name", "Progress" }, 0));

    JButton btnBegin = new JButton("Begin");
    btnBegin.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            DefaultTableModel model = (DefaultTableModel) table.getModel();
            MyThreadClass newThread = new MyThreadClass(model, threadNumber++);
            newThread.start();

            model.addRow(new Object[] { "Thread " + threadNumber, "Column 2" });
        }
    });

    JFrame frame = new JFrame();
    frame.add(btnBegin, BorderLayout.NORTH);
    frame.add(table);
    frame.setSize(400, 400);
    frame.setVisible(true);
}

static class MyThreadClass extends Thread {
    private final DefaultTableModel model;
    private final int threadNumber;

    public MyThreadClass(DefaultTableModel model, int threadNumber) {
        super();
        this.model = model;
        this.threadNumber = threadNumber;
    }

    @Override
    public void run() {
        for (int i = 0; i <= 5; i++) {
            final int index = i;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    model.setValueAt(index * 20, threadNumber, 1);
                }
            });
        }
    }
}

}

请注意,SwingUtilities.invokeLater 的使用很重要,因为必须在 EDT 中刷新视图。

【讨论】:

    【解决方案2】:

    如果你想在运行时更新列并且如果你知道你想更新哪一行,你可以这样使用它:

    int row; // row number you want to update.
    int column = 1; // You want to update the first row.
    DefaultTableModel model = (DefaultTableModel)table.getModel();
    Object value = "New Value Of This Cell";
    model.setValueAt(value, row, column);
    

    您可以将您的表格以及线程显示的行传递或设置给 MyThreadClass,以便它可以自行更新其行。

    你可以像这样在 MyThreadClass 中编写一个方法:

    public void setTableAndRow(int row, JTable table) {
        this.table = table;
        this.row = row;
    }
    

    您可以在创建线程时传递这些参数:

    btnBegin.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            DefaultTableModel model = (DefaultTableModel) table.getModel();
            MyThreadClass myThread = new MyThreadClass(country, category);
            Thread newThread = new Thread(myThread);
            /**
             * We know, if there is n rows starting from 0,
             * index of the row that we're adding is n.
             */
            int row = model.getRowCount();
            myThread.setTableAndRow(row, table);
            // Now we add the row before starting the thread, because it
            // will try to reach that row, we don't want any exceptions.
            model.addRow(new Object[]{"Thread " + threadNumber, "Column 2"});
            newThread.start();
        }
    });
    

    【讨论】:

      【解决方案3】:

      建议:

      • 使用 SwingWorker 对象创建后台线程。
      • 从 SwingWorker 获取更新的一种方法是使用其发布/处理方法对。这允许后台线程在 Swing 事件线程上将数据传递给 Swing 应用程序。这将允许后台进程将数据“推送”到 GUI。
      • 获取更新的另一种方法是将 PropertyChangeListener 添加到 SwingWorker 并让 SwingWorker 更新绑定属性。要么工作正常。这将允许将数据从后台进程“拉”到 GUI。
      • 要更新特定数据行中的数据,您需要以某种方式将模型的一行与您所关注的线程连接起来。您始终可以使用getValueAt(...) 遍历表模型的某个列的单元格,直到找到包含与线程匹配的数据的单元格,可能是被监视类的字段。然后,您可以使用 JTable 的 setValueAt(...) 更新该行的不同列所保存的数据

      【讨论】:

        【解决方案4】:

        我认为SwingUtilies.invokeLater() 是您要查找的内容,因此您可以访问event dispatch thread

        【讨论】:

          猜你喜欢
          • 2014-12-16
          • 2012-10-11
          • 1970-01-01
          • 2017-01-04
          • 1970-01-01
          • 1970-01-01
          • 2023-03-29
          • 1970-01-01
          相关资源
          最近更新 更多