线程和jtable

时间:2012-11-15 22:32:23

标签: java multithreading swing jtable event-dispatching

我的jtable有问题。

我有许多线程,每个线程都必须向jTable添加一行,但表格仍为空。我正在使用netbeans,图形完全独立于逻辑。请有人帮帮我吗?


这是我用来添加行的代码

MainGui.java

public void addToTable(String from, String to, int request, int response, String timeElapsed) {
    Object [][] temp = new Object [data.length + 1][5];

    for (int i = 0; i < data.length; i++) {
        for (int j = 0; j < 5; j++) {
            temp[i][j] = data[i][j];
        }
    }

    temp[data.length][0] = from;
    temp[data.length][1] = to;
    temp[data.length][2] = request;
    temp[data.length][3] = response;
    temp[data.length][4] = timeElapsed;

    data = temp;
    table.setModel(new DefaultTableModel(data, columnName));
}

MyThread.java

public void run() {
    try {
        MainGui mg = new MainGui();
        mg.addtotable("null", "null", 0, 0, "null");
    } catch (Exception e) {
    }

6 个答案:

答案 0 :(得分:7)

Swing的第一条规则 - 不要从事件调度线程以外的任何线程修改UI

首先,使用SwingUtilities#invokeLater确保您的更新调用已同步,或者更新对代码路径SwingUtilities#invokeAndWait

是否至关重要

向表模型添加行时,您负责触发通知视图模型已更改所需的更新事件。

如果您使用的是DefaultTableModel,那么这将为您完成,如果您使用的是AbstractTableModel,或者您拥有TableModel,那么您需要自己执行此操作。

最简单的方法是编写一个从AbstractTableModel延伸并从add方法中调用AbstractTableModel#fireTableRowsInserted(int, int)的实现,这将告诉JTable模型已添加行并将导致表格会自动更新。

不要被愚弄,使用fireTableRowsInserted通常比在向表模型添加行时使用fireTableDataChanged更快,因为整个表不需要重新绘制。如果您已经显着更改了表格(添加/删除/更新了许多行),那么fireTableDataChanged将比单个插入/删除/更新的系列调用更快。

有关详细信息,请查看How to Use TablesConcurrency in Swing

<强>已更新

因为看起来我可能没有说清楚。该模型负责解雇事件。这意味着,在您的add方法中,您应该调用fireTableRowsInserted。您应该避免从外部源调用这些方法。

答案 1 :(得分:1)

Swing不是线程安全的。如果需要从AWT事件派发线程以外的线程修改Swing组件,请使用

SwingUtilities.invokeLater(new Runnable(){public void run() {
 // your code
}});

答案 2 :(得分:0)

您能否澄清一下如何添加行?希望使用模型,对吧? 添加新行后,您必须调用模型的方法fireTableDataChanged / 不是最佳选项 /或fireTableRowsInserted / 更好 / 并且不要忘记使用SwingUtilities.invokeLater来避免Swing的问题

答案 3 :(得分:0)

public class TM extends AbstractTableModel {
final List<Integer>ids;

public TM() {
    ids = new ArrayList();
}

@Override
public int getRowCount() {
    return ids.size();
}

@Override
public int getColumnCount() {
    return 1;
}

@Override
public String getColumnName(int column) {
    if(column == 0) {
        return "ID";
    } else {
        return "UNDEF";
    }
}

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    if(columnIndex == 0) {
        return ids.get(rowIndex);
    } else {
        return "NaN";
    }
}

public void addId(final int id) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            insertNewRow(id);
        }
    });
}

private void insertNewRow(int id) {
    ids.add(id);
    int rowIndex = ids.size();
    fireTableRowsInserted(rowIndex, rowIndex);
}

}

//Somewhere in your code
TM myModel = new TM();
myTable = new JTable(myModel);


//Somewhere from thread:
myModel.addId(123);

//Somewhere from another thread:
myModel.addInd(455);

答案 4 :(得分:0)

此外,在尝试更新JTable的模型时,在更新模型之前删除任何tableModelListener非常重要。我用model.addColumn()table.moveColumn()看到了这个观察结果。确保在对模型进行任何更改后添加tableModelListener

答案 5 :(得分:-1)

我希望你知道Swing不是线程安全的(除了少数例外)。你需要在你的代码中处理它。