我有一个多线程程序,我正在尝试使用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"});
}
});
答案 0 :(得分: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,以便它可以自行更新其行。
您可以像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();
}
});
答案 1 :(得分: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中刷新视图。
答案 2 :(得分:3)
建议:
getValueAt(...)
遍历表模型的某个列的单元格,直到找到包含与该线程的数据匹配的数据,可能是监视类的字段。然后,您可以使用JTable的setValueAt(...)
答案 3 :(得分:1)
我认为SwingUtilies.invokeLater()正是您所寻找的,因此您可以访问event dispatch thread。