2012-08-09 49 views
1

我有一個多線程程序,我試圖用JTable來查看每個線程的進度。每個線程都是JTable的一行。我已經發布了我現在擁有的簡化和相關的代碼。每次按啓動時,都會啓動一個新線程,並將該行添加到JTable。但是,如何更新「列2」哪一行屬於該線程從正在運行的線程?Java從另一個線程更新jtable行

在主這是我

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"}); 
    } 
}); 
+0

來更新該行所在行的另一列所保存的數據嗎?是否要在添加或更新列後更新列?你想用這個專欄做什麼? – sedran 2012-08-09 20:52:55

回答

3

如果您可以從該類中添加字段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被刷新。

3

,如果你想在運行時更新列,如果你知道你要更新哪一行,你可以用這種方式:

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的行,以便它自己更新其行。

你可以寫一個方法insie 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(...)
相關問題