2010-11-22 2 views
4

私はたくさん試しましたが、うまく動作しないようです。スレッド内のJFrameラベルを更新するには? - Java

次の例でEDTを使用するように言われました。

SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      // Modify the GUI here 
     } 
}); 

私はこのトピックについて多くのことを読んだが、まだ理解していません。私はスレッドが何かを得るが、.invokeLaterはまだ私には意味をなさない。正直なところ、を詳しく説明してください。これは大きな助けになるでしょう!プログラムの

目標:は常にGUIで、その後自分自身を更新するために毎秒作成され、ランダムに生成されたキーを取得します。

+1

下記の@John V.の答えに加えて、この記事を読むことができます:[スレッドとスイング](http://java.sun.com/products/jfc/tsc/articles/threads/threads1 .html) – casablanca

答えて

3

したがって、EDT(イベントディスパッチスレッド)があります。画面に表示されるすべてのアクションは、EDTによって実行されます。スイングアプリケーションごとに1つのEDTがあります。

あなたは任意のスレッドに属していますが、そのスレッドを通じてQUIを更新したいですか?まあ、私はスイングアプリケーションごとにEDTが1つしかないと言いましたので、ラベルを表示するようEDTに伝える必要があります。

ここで考えているのは、このRunnableを、EDTがプルするキューにプッシュすることです。結局のところ、あなたの実行可能ファイルは、その前に他のすべてのアクションが完了すると、EDTによって処理されます。

0

既知のスケジュールでUIを更新する場合は、次のような方法を試してみてください。これは、JFrameが1秒ごとに更新するコンポーネントであることを前提としています。

private static final int WAIT_LENGTH = 1000; // 1 second 
private JFrame frame = new JFrame(); 

// Thread will update the UI (via updateUI() call) about every 1 second 
class UIUpdater extends Thread { 
    @Override 
    void run() { 
    while (true) { 
     try { 
     // Update variables here 
     } 
     catch (Exception e) { 
     System.out.println("Error: " + e); 
     } 
     finally { 
     frame.repaint(); 
     Thread.sleep(WAIT_LENGTH); 
     } 
    } 
    } 
} 

このスレッドを開始するには:

UIUpdater t = new UIUpdater(); 
t.start(); 
+0

.updateUI();エラーが発生し続け、いつでも.setText()でラベルを変更しようとします。あなたが投稿した//ここで変数を更新する私はいつも私を助けてくれないことに終わります。だから私はJFrameの代わりにmainFrame(前に使用していたJFrameを拡張する)が必要なので、動作しないと思ったので、基本的にはどこにこれを更新させるかはわかりません。私は確かに "Filthy Rich Clients"と書かれた本を読むつもりです... – Zeveso

+0

'component.repaint()'はあなたが探している行に沿っています。ごめんなさい。私は私の答えを更新しました。 –

1

を私はあなたが本Filthy Rich Clientsを取得をお勧めします。スイングのスレッディングモデルについて非常に詳細に説明する章があります。

スイングでは、GUIを変更するコードはすべて、イベントディスパッチャスレッドで実行する必要があります。そこで使用しているSwingUtilitiesクラスは、EDTによって送出されるイベントキューにイベントを簡単にポストする方法を提供します。これはinvokeLaterメソッドの機能ですが、最終的にEDTで実行される引数としてnew Runnable()を引数にとります。

帳から:

invokeLater()の実装は、Runnableをを含む特別な イベントを作成し、キューイングの 世話をします。この イベントは、 他のイベントと同様に、受信した の順序でEDTで処理されます。その時刻になると が実行され、 Runnableのrun()メソッドが実行されます。

+0

私は今夜その本を手に入れようとしています。 – Zeveso

0

これは、すべてのGUIプログラミングのかなり一般的な要素です。 GUIの描画、入力の取得、コールバックの実行を処理するスレッドが1つあります。別のスレッドがGUI関連のオブジェクトを変更しようとすると、GUIスレッドと競合します。例えば、何かを描いている途中で、別のスレッドから色を変えたとします。

すべてのinvokeLaterは、GUIスレッドを実行するために何かをキューに入れます。 「後で」これは実際にはほとんど瞬時に実行されますが、現在のスレッドはそれを待つ必要はありません。 GUIスレッドは、ドローを行っているか、コールバックが返されるのを待っている可能性があります。

0

メンバーので、我々はそれを変更し、まだ内部クラスから

protected long secret=0; 

を使用することができますする必要がありますが...これはどこかにそれが実行得るでしょう、あなたのコードにする必要があります...

それが適切に塗るように
JFrame f = new JFrame("foo"); 
new Thread(){ 
     public void run() { 
      for(;;){ 
       try { 
        sleep(1000); 
       } catch Interrupted (Exception ix){ 
        return; 
       } 
       // TODO update your secret key here 
       // please don't use random() 

       SwingUtilities.invokeLater(new Runnable() { 
        public void run() { 
         f.setTitle("secret "+x); 
        } 
       }); 
      } 
     } 
    }).start(); 

....

は今までEDTからスイングを更新します。

EDT(イベントハンドラのコード実行中)に、本当に必要な場合はpaintImmediately()を呼び出すことができます。

関連する問題