0

JTable のカスタム テーブル モデルを作成しました。

class MessageTableModel{

    private static Set<Message> messages = Collections.synchronizedSet(new TreeSet<Message>());

    .
    .
    .

    public void setMessages(List<Message> newMessages) {
        Collections.sort(newMessages);
        Iterator<Message> it = messages.iterator();
        while (it.hasNext()) {
            Message mess = it.next();
            if (!newMessages.contains(mess)) {
                it.remove();
                this.fireTableDataChanged();
            }
        }
        for (Message message : newMessages)
            if (message.isOrderStatusMessage())
                if (!messages.contains(message)) {
                    addMessage(message);
                }
        this.fireTableDataChanged();
    }

    public Message getMessageAtRow(int row){
        return (Message) messages.toArray()[row];
    }
}

問題は、定期的に setMessages() メソッドを呼び出して、テーブルの値を更新するスレッドがあることです。この更新中に行を取得しようとすると:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1

この行で:

return (Message) messages.toArray()[row];

メソッド getMessageAtRow() が変更が完了するのを待つようにする方法、またはこの問題の別の解決策はありますか?

4

1 に答える 1

3

Swing はシングルスレッドです。イベント スレッド外のスレッドでモデルを変更することはできません。これを修正する最も簡単な方法は次のとおりです。

public void setMessages(List<Message> newMessages) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
            Collections.sort(newMessages);
        Iterator<Message> it = messages.iterator();
        while (it.hasNext()) {
            Message mess = it.next();
            if (!newMessages.contains(mess)) {
                it.remove();
                this.fireTableDataChanged();
            }
        }
        for (Message message : newMessages)
            if (message.isOrderStatusMessage())
                if (!messages.contains(message)) {
                    addMessage(message);
                }
        this.fireTableDataChanged();
    }
  )};
}

また、fireTableDateChanged()イベント スレッドでのみ呼び出す必要があります。

于 2012-04-16T19:36:59.007 に答える