web-dev-qa-db-ja.com

java.awt.EventQueue.invokeLaterの説明

Swingコンポーネントを制御するためにJava.awt.EventQueue.invokeLaterを使用しなければならない理由は非常に興味深いです。

なぜ通常のスレッドではできないのですか?舞台裏で何が起こっているのでしょうか? JFrameがある場合に気づいたことから、エラーを発生させることなくメインスレッドから可視性をtrueまたはfalseに設定できますが、動作するようです。それで、Java.awt.EventQueue.invokeLaterを使用して正確に何を達成できますか?私はSwingUtilities.invokeLaterを使用できることも十分に認識していますが、 ここで説明 のように、それらはまったく同じもののようです。

説明してくれてありがとう。うまくいけば、これは有効な質問です。

編集:wumpzの質問に答えるためにjframeを作成できます

JFrame frame = new JFrame("Hello world");
frame.setSize(new Dimension(300, 300));
frame.setPreferredSize(new Dimension(300, 300));
frame.setMaximumSize(new Dimension(300, 300));
frame.setMinimumSize(new Dimension(300, 300));
frame.setVisible(true);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

そして、それが作成されたのと同じスレッドで、以下を実行します。

for (int i = 0; i < 34; i++)
{
    System.out.println("Main thread setting to "+(!frame.isVisible()));
    frame.setVisible(!frame.isVisible());
}

苦情もありません。

33
Quillion

完全なSwing処理は、EDT(Event Dispatching Thread)というスレッドで実行されます。したがって、このスレッド内で長期にわたる計算を計算する場合、GUIをブロックします。

ここに行く方法は、異なるスレッド内で計算を処理し、GUIの応答性を維持することです。最後に、GUIを更新します。これは、EDT内で-を行う必要があります。今EventQueue.invokeLaterが出てきます。 Swingsイベントリストの最後にイベント(Runnable)をポストし、以前のすべてのGUIイベントが処理された後に処理されます。

また、EventQueue.invokeAndWaitはここで可能です。違いは、GUIが更新されるまで計算スレッドがブロックすることです。したがって、EDTからこれを使用してはならないことは明らかです。

Swing GUIを別のスレッドから更新するには、notに注意してください。ほとんどの場合、これにより奇妙な更新/更新の問題が発生します。

それでも、Javaメインスレッドから単純なJFrameを開始するコードがあります。これにより問題が発生する可能性がありますが、Swingを防ぐことはできません。 :

public static void main(String args[]) {
    Java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new NewJFrame().setVisible(true);
        }
    });
}
41
wumpz

すべての サポートされているプラ​​ットフォーム は、シングルスレッドグラフィックライブラリを提供します。 Swingはクロスプラットフォームです。したがって、Swing GUIオブジェクトは、 イベントディスパッチスレッド でのみ構築および操作する必要がありますonly

余談ですが、 SwingUtilities.invokeLater() はバージョン1.3以降のEventQueue.invokeLater()のカバーです。

11
trashgod