9

Swingコンポーネントを構築し、イベントを処理するすべてのコードは、イベントディスパッチスレッドによって実行される必要があることを読みました。この方法を使用することで、これがどのように達成されるかを理解していSwingUtilities.invokeLater()ます。mainGUIの初期化がメソッド自体で行われる次のコードについて考えてみます。

public class GridBagLayoutTester extends JPanel implements ActionListener {   
    public GridBagLayoutTester() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        JButton button = new JButton("Testing");
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        button.addActionListener(this);
        add(button, gbc);
    }

    public void actionPerformed(ActionEvent e) {
        System.out.println("event handler code");
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("GridBagLayoutDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(new GridBagLayoutTester(), BorderLayout.CENTER);
        frame.setSize(800, 600);
        frame.pack();
        frame.setVisible(true);
        System.out.println("Exiting");
    }   
}

このコードが完全に機能するのはどうしてですか?JFrameメインスレッドで他の多くのメソッドを構築して呼び出しています。ここでEDTが正確にどこに現れているのかわかりません(どのコードが実行されていますか?)。クラスのコンストラクターGridBagLayoutTesterもメソッドから呼び出されてmainいます。これは、EDTがクラスを実行していないことを意味します。

要するに

  1. EDTはいつ開始されますか?(このコードの実行中にEDTが開始された場合、JVMはmainメソッドとともにEDTを開始しますか?)
  2. ボタンのイベントハンドラーコードはEDTで実行されますか?
4

4 に答える 4

12

EDTがフレームと対話する前に、メインスレッドでフレームを構築しているため、コードは完全に機能します。技術的には、これを行うべきではありませんが、技術的には、JFrameが表示されるまで操作できないため、この特定の状況下で行うことができます。

知っておくべき主なポイントは、Swingコンポーネントはスレッドセーフではないということです。これは、同時に複数のスレッドから変更できないことを意味します。これは、すべての変更がEDTからのものであることを確認することで解決されます。

EDTは、ユーザーとの対話専用のスレッドです。ユーザーから生成されたイベントはすべて、常にEDTで実行されます。ユーザーインターフェイスの更新はすべてEDTで実行されます。たとえば、を呼び出すときはComponent.repaint()、任意のスレッドからこれを呼び出すことができます。これは、コンポーネントにペイントが必要であることを示すフラグを設定するだけで、EDTは次のサイクルでそれを実行します。

EDTは自動的に開始され、システムの実装と非常に密接に関連しています。これは、JVM内で適切に処理されます。通常、これは、ユーザーの操作を処理するウィンドウシステム内の単一のスレッドに関連付けられます。もちろん、これは実装に大きく依存します。良い点は、これについて心配する必要がないことです。知っておく必要があります。Swingコンポーネントを操作する場合は、EDTで実行してください。

同様に、重要なことがもう1つあります。外部リソースに対して長時間の処理またはブロックを実行し、ユーザーによって生成されたイベントに応答して実行する場合は、EDTから離れた独自のスレッドで実行するようにスケジュールする必要があります。これを怠ると、長時間の処理が実行されるのを待つ間、ユーザーインターフェイスがブロックされます。優れた例としては、ファイルからの読み込み、データベースからの読み取り、ネットワークとのやり取りなどがあります。このメソッドを使用して、EDT(任意のスレッドから呼び出すことができるニュートラルメソッドを作成するのに便利)を使用しているかどうかをテストできますSwingUtilities.isEventDispatchThread()

これは、EDTを処理するSwingプログラミングを作成するときに頻繁に使用する2つのコードスニペットです。

void executeOffEDT(){
  if(SwingUtilities.isEventDispatchThread()){
    Runnable r = new Runnable(){
      @オーバーライド
      public void run(){
        OutsideClass.this.executeOffEDTInternal();
      }
    };
    new Thread(r).start();
  } そうしないと {
    this.executeOffEDTInternal();
  }
}

void executeOnEDT(){
  if(SwingUtilities.isEventDispatchThread()){
    this.executeOnEDTInternal();
  } そうしないと {
    Runnable r = new Runnable(){
      @オーバーライド
      public void run(){
        OutsideClass.this.executeOnEDTInternal();
      }
    };
    SwingUtilities.invokeLater(r);
  }
}
于 2010-09-03T14:19:07.157 に答える
3

イベントディスパッチスレッドは、その名前が示すように、イベントを処理する必要があるたびにSwingによって呼び出されます。

与えた例では、アクションイベントを処理する必要がある場合、[テスト]ボタンが自動的にactionPerformedメソッドを呼び出します。したがって、actionPerformedメソッドのコンテンツは、イベントディスパッチスレッドによって呼び出されます。

最後の2つの質問に答えるには:

  • Swingフレームワークがロードされると、EDTが自動的に開始されます。このスレッドの開始を気にする必要はありません。JREがこのタスクを処理します。
  • イベントハンドラコードはEDTによって実行されます。Swingインターフェースが生成するすべてのイベントはプールされ、EDTがそれらを実行する責任があります。
于 2010-09-03T14:18:53.210 に答える
1

new JFrame1) inか in かはわかりませんが、setVisibleオンデマンドで初期化されます。これが、(メイン プロセス スレッドを介した) メイン メソッドの最後でプロセスが終了しないことです。EDT が起動され、次のイベントを待っているループ ブロックに入っています。

2) 決定的に。そのループは OS からイベントを受け取り、JButton を見つけて、イベントが発生したことを伝えます。次に、ボタンはリスナーを呼び出します。すべて EDT で発生します。

プロセスを強制終了する (またはメイン ウィンドウを閉じる) ときに呼び出す Swing コードを確認して、EDT が終了する場所を確認することができます。

于 2010-09-03T14:18:27.053 に答える