3

私は約 10 の異なるデータソース (統計/エラー ログなど) を持つアプレットに取り組んでいます。各データソースは、単一のネットワーク接続によって更新され、オブザーバー メカニズムを介して更新を報告します。アプレットには、データの一部を表示するさまざまなビューがあります。すべてのビューは、データの一部のみに関心があり、必要な Observables で Observer として自身を登録します。

The views(extended JPanels) mostly consist of standard swing components (e.g. JLabels, JButton, ...). Some attributes of the components in the views depend on information from the underlying data model.

Example:

StatisticPanel::paintComponent(Graphics g) {
  clearStatisticButton.setEnabled(stat.hasEntries());
  minValueLabel.setText(stat.getMinValue());
  super.paintComponent(g);
}

This logic is implemented in the paintComponent() method of the StatisticPanel and the update() methods just calls repaint(), because I didn't want the manipulate the components outside of the EDT.

Is this the intended way of updating swing components in a multi-threaded environment? Is it better to use a Runnable with SwingUtitlies.invokeLater()? Are there better approaches for this problem?

4

2 に答える 2

6

私はcamickrの推奨事項に二番目ですが、このコードスニペットに関して:

StatisticPanel::paintComponent(Graphics g) {
  clearStatisticButton.setEnabled(stat.hasEntries());
  minValueLabel.setText(stat.getMinValue());
  super.paintComponent(g);
}

paintComponent メソッド (最初の 2 つのメソッド) に描画以外のメソッドがあり、それは 1) このメソッドを可能な限り無駄なく高速にしたいため、描画関連のコードのみを持ち、2) であってはなりません。このメソッドが呼び出されたとき、または呼び出されたとしても、完全に制御することはできません。そのため、描画に関連しないコードとプログラム ロジックはそこに属しません。これらの理由から、それらをそこから取り除くことを強くお勧めしますが、代わりに、ほとんどの Swing コードと同様に EDT で、paintComponent とは別に呼び出す必要があります。

EDIT 1
私は専門家ではありませんが、StaticPanelに次のようなメソッドを与えたらどうですか:

   public void doMyUpdate() {
      if (SwingUtilities.isEventDispatchThread()) {
         clearStatisticButton.setEnabled(stat.hasEntries());
         minValueLabel.setText(stat.getMinValue());
      } else {
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               clearStatisticButton.setEnabled(stat.hasEntries());
               minValueLabel.setText(stat.getMinValue());
            }
         });
      }
      repaint(); // if the paintComponent method has more than just a super call.
   }

EDIT 2
また、このスレッドをご覧ください: check-if-thread-is-edt-is-necessary

于 2011-05-24T15:01:47.253 に答える
4

repaint() は、コンポーネントの再描画をスケジュールする Swing RepaintManger を呼び出すために使用されるため、直接 repaint を呼び出すだけで問題ありません。RepaintManager は、すべての再描画が EDT で行われるようにします。

于 2011-05-24T14:59:17.720 に答える