6

実行のメインスレッドからいくつかのダイアログボックスをユーザーに表示する必要がある単純なグルーヴィーなスクリプトがあります。

私のスイングの知識は限られており、錆びていますが、イベントディスパッチスレッド (EDT) に GUI を保持するように注意する必要があることについて読んだことを思い出します。

メイン スレッドから静的JOptionPane.showMessageDialogメソッドを呼び出すだけで、GUI を EDT に保持するという正しい慣行に違反すると想定するのは正しいでしょうか?

次のコード例のように、実際に swing.utils.invokeAndWait メソッドを使用する必要がありますか?


void showHelloThereDialog() 
        throws Exception {
    Runnable showModalDialog = new 
      Runnable() {
        public void run() {
            JOptionPane.showMessageDialog(
               myMainFrame, "Hello There");
        }
    };
    SwingUtilities.invokeAndWait
       (showModalDialog);
}

上記では、invokeAndWait の完了後にメッセージ ダイアログ以外の値を使用できるようにするために何もしません。

おそらく、グルーヴィーな「クロージャー」が Runnable を実装するという事実は、上記よりも単純なコードになるでしょう。

invokeAndWait は必要ですか? もしそうなら、誰かが正しい実装の例を挙げて、groovyを使用してconfirmDialogのような結果を得ることができますか?

4

3 に答える 3

8

JOptionPaneの showXXXDialog() のいずれかへの呼び出しは、ユーザーが [OK]、[キャンセル] などを選択するまでブロックされます。一般に、イベント ディスパッチ スレッド (EDT) にこのような遅いブロッキング命令を配置することはありません。これは、他のすべての GUI コンポーネントがフリーズするためです。したがって、EDT を使用しないという本能は良いことですが、間違っていることもあります。その理由は、他の人が述べているように、メソッドは GUI コンポーネントを作成し、これは常に EDT で行う必要があります。しかし、ブロッキングはどうですか?EDT で実行しても、問題なく動作することがわかります。理由はソースコード内にあります。このクラスは Dialog オブジェクトを作成し、続いてJOptionPaneを呼び出します。最初の はスレッドをブロックするものです。コメント (または javadoc) を読むと、メソッドについて次のように書かれていることがわかります。show()dispose()

ダイアログがモーダルで、まだ表示されていない場合、hide または dispose を呼び出してダイアログを非表示にするまで、この呼び出しは戻りません。ツールキットは、このメソッドを呼び出したイベント ポンプがブロックされている間、別のイベント ポンプが確実に実行されるようにするため、イベント ディスパッチ スレッドからモーダル ダイアログを表示することができます。

JOptionPaneそのため、EDT がブロックされているにもかかわらず、EDT で実行することは完全に安全です。明らかに、EDT から Dialog のメソッドを呼び出すことは安全ですが、そのメソッドが GUI コンポーネントの作成、リスナーの追加、モーダル時の他のコンテナーへのアクセス、それらへの入力のブロックなどを行っているためshow()、同じことは当てはまりません。これらすべてが必要なわけではありません。JOptionPaneこれはスレッドセーフではなく、問題が発生する可能性があるためです。確かにJOptionPane、EDT を使用していないときに問題が発生したことはありません。ダイアログのコンテナーに null を渡し、不変オブジェクトのみを指定します (Strings)フィールドへの引数は、関連するすべてのGUIコンポーネントが表示されていないときに同じスレッド内で作成およびアクセスされるため、何か悪いことが起こる可能性を大幅に削減します(おそらく私が知る限り排除します)。ただし、安全にEDTに入れる必要があります. 呼び出すのはそれほど難しいことではありませんSwingUtilities.invokeAndWait()

于 2012-07-21T04:59:34.433 に答える
5

これは EDT にある必要があるため、invokeAndWait または invokeLater が必要です。JOptionPane.showMessageDialog のコードが最終的に Swing コンポーネントを作成および変更するため、それがわかります。Java 6 の時点で、Sun は、Swing コンポーネントのすべての操作 (実現されているかどうかにかかわらず) は EDT で行う必要があると述べています。

http://download.oracle.com/javase/6/docs/api/javax/swing/package-summary.html

http://www.velocityreviews.com/forums/t707173-why-does-jdk-1-6-recommend-creating-swing-components-on-the-edt.html

于 2011-03-30T20:37:44.477 に答える
4

groovy.swing.SwingBuilderを見てください。これは、invokeAndWaitとinvokeLaterをカプセル化します。あなたの例は次のように書くことができます:

import groovy.swing.SwingBuilder
import javax.swing.*
import java.awt.*

def swing = new SwingBuilder()
def myMainFrame = new Frame()

swing.edt {
    JOptionPane.showMessageDialog(
        myMainFrame, "Hello There");
}
于 2011-03-30T20:58:21.613 に答える