0

予備質問

Google Guava イベントが発生したときに更新されるように JTable を作成するにはどうすればよいですか (そしてスレッドセーフであることを保証します)。

簡単な方法はmodel.setValueAt(aValue, row, column);

2 つの問題:

  • JTableModel の標準データ構造を使用すると、自分がどの行にいるのかわかりません。
  • JTableModel の標準データ構造を使用しているため、このデータを他のコンポーネントに使用することはできません
  • これはスレッドセーフではありません(と思います)

JTableModel を ConcurrentHashMap を使用するように変更することを考えましたが、これはそれを拡張する意図された目的ではないようです。これは奇妙なバグへのルートだと思います。

このすべての中で私は非常に迷っています。最初に何を調べるべきかのガイドを提供していただければ、非常に役立ちます.

より詳しい質問

イベントは EVT にはありません。実行したことを確認するためSwingUtilities.isEventDispatchThread()に、結果は false でした。

私が今すべきだと思うこと:

@Subscribe
public void handleMessage(DataStructure newInformation) {
  // handle the information

  SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        tableModel.setValueAt(...); // update table1
        tableModel2.setValueAt(...); // update table2
    }
  });
}

イベントでは、テーブルから完全に独立した情報を取得します。情報がどの行に関連しているかを知る方法が必要です。
モデル内のベクトル全体をいつでも循環できますが、マップまたは配列を使用できるソリューションを探しています。

4

2 に答える 2

3

Swing コンポーネントへのすべての変更は、イベント ディスパッチ スレッドで行う必要があります。を呼び出して、イベント ディスパッチ スレッドにいるかどうかをテストできますSwingUtilities.isEventDispatchThread()。true が返された場合は、モデルを直接変更できます。false を返す場合、SwingUtilities.invokeLater()(またはSwingUtilities.invokeAndWait())で実行される Runnable 内にラップして、EDT で更新を行う必要があります。

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        tableModel.setValueAt(...);
    }
});

このイベントが何であるか、またテーブル モデルが何であるかはわかりませんでしたが、テーブル モデルのおかげで、取得したイベントに対応する行と列を見つけることができる必要があります。 . 通常、AbstractTableModel が使用され、List<SomeBean>. SomeBeanリストのメソッドを使用すると、更新するインスタンスのインデックスを見つけることができるはずです。

編集:

前述したように、テーブル モデルを定義する一般的な方法は、AbstractTableModel を拡張し、ラップされた List に基づいてメソッドを実装することです。ただし、テーブル モデル コントラクトが実装されていれば、List の代わりに、または List に加えて Map を使用したり、モデルにメソッドを追加したりすることを妨げるものは何もありません。getValueAt()List は、などのメソッドを実装するために使用されgetRowCount()、マップを使用すると、たとえば、リスト内のオブジェクトのインデックスをすばやく見つけることができます。もちろん、すべてをカスタム テーブル モデルにカプセル化し、両方のコレクションを同期させるのはあなたの仕事です。

とはいえ、リストを反復処理して適切な行を見つけるという単純な解決策を採用し、パフォーマンスの問題が本当にある場合にのみ最適化を試みます (これはおそらく巨大なテーブルでのみ発生します)。2 つのコレクションを維持すると、単にリストをループするよりもオーバーヘッドが大きくなる可能性があります。時期尚早に最適化しないでください。それは諸悪の根源です。

于 2012-11-02T15:46:22.367 に答える
1

私の一般的なアドバイスは、を呼び出すことによって実装するAsyncEventBuswithを使用することです。これにより、そのイベントバスのすべてのイベントハンドラーがEDTでのみ呼び出されるようになります。Executorexecute(Runnable)SwingUtilities.invokeLater(Runnable)

EDTで処理したくないイベントが多数ある場合は、2つのイベントバスを使用できます。EDTでは1つの呼び出しイベントハンドラー(UIイベントバス)のみを使用できます。次に、UIコンポーネントがUIイベントバスにサブスクライブします。次に、受信したイベントをUIイベントバスに送信するだけのメインイベントバスに登録されている中間オブジェクトを使用して、メインイベントバスに特定のタイプのイベントをUIに転送させることができます。

于 2012-11-02T18:06:55.680 に答える