7

今日、この質問に答えることができるかどうかを確認しようとしました。Event Dispatch Thread( EDT )を完全には理解していないことに気付きました。グーグルはそれを確認して助け、なぜ私がそうしないのかを明らかにしました。(これも理解に関係するかもしれません。)

コードは GUI を設定し、後で (前の質問のように) フラグが設定解除されるまでテキスト フィールドを更新します。

いくつか質問/要望があります。

  • swingInit両方の呼び出し (toとdoIt) がブロックの外側にある場合 (示されているように)、以下のコードが正常に実行される理由を説明してください。これはinvokeLater、両方の呼び出しが GUI に影響を与えたりクエリを実行したりしますが、どちらも EDT で実行されていないためです (そうですか?)。それは失敗を招いていませんか?

  • call toswingInitが inside とdoItoutside の場合もコードが実行されinvokeLaterます。これswingInitは EDT で実行されますが、EDT でdoIt実行することは問題ではありませんか? (これが機能したことに驚きました。そうすべきだったのでしょうか?)

  • どこにあるかに関係なく、doIt内部にある場合にハングする理由を理解していると思います: の目的は、GUIを初期化することだけです (右?)。invokeLaterswingInitinvokeLater

  • ブロック内ではなくdoIt、EDT でのみ (おそらく発生したイベントから) 開始する必要がありますか?invokeLater

(EDT の概念の歴史は興味深いものです。常にそうであるとは限りません。それを理解できない理由については、上記のリンクを参照してください。)

import static java.awt.EventQueue.invokeLater;
import java.awt.event.*;
import javax.swing.*;

public class Whatever 
{
  static boolean flag = true;
  static JTextField tf = new JTextField("Hi",20);
  static JPanel p = new JPanel();
  static JFrame f = new JFrame();
  static JButton b = new JButton("End");

  public static void main(String[] args)
  {
    swingInit();

    invokeLater
    (
      new Runnable()
      {
        @Override
        public void run() 
        {
    //    swingInit();
    //    doIt();
        }
      }
    ); 
   doIt();      
  } 

  static void swingInit()
  {
     b.addMouseListener
    (
        new MouseAdapter()
        {
          @Override
          public void mouseClicked(MouseEvent e)
          {
            flag = false;
            JOptionPane.showMessageDialog(null,"Clicked... exiting");
            System.exit(0);
          }
        }
    );

    p.add(tf);
    p.add(b);
    f.add(p);
    f.setVisible(true);
    f.pack();
    f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
  }

  static String getInfo(){
    return "Hello... " + Math.random();
  }

  static void doIt(){
    while(flag)     
      tf.setText(getInfo());
  }; 
}
4

2 に答える 2

3

それぞれの箇条書きを取り上げます。

  • コードはメイン スレッドで起動されます。EDT は並行して実行されます。 swingInitEDT の制御下にある UI を構築した後に戻りdotIt、メイン スレッドで並行して実行できるようにする

  • 上記と同様の状況ですが、ここでは EDT での UI の構築を保証しています ( Oracleの推奨に従って)。

  • swingIt長時間実行されるタスクが EDT に配置され、表示 ( の前に配置された場合) または描画と相互作用 ( の後に配置された場合)が妨げられます。the purpose of invokeLater is ONLY to initialize the GUI目的は、スレッドセーフでない Swing 呼び出しを EDT に配置することです。メインメソッド内の場合は、使用することをお勧めしますSwingUtilities.invokeAndWait

  • このように UI を更新したい場合は、SwingTimer.

EDT の外部で EDT 固有の非スレッド セーフ コードを実行しても、失敗は保証されませんが、失敗を招きます (2 つ (またはそれ以上) のスレッドが同時にデータを更新しようとした場合の競合を介して)。

私はかつて謎NullPointerExceptionLookAndFeel. 学んだ教訓。

于 2015-05-08T19:46:20.937 に答える