Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JOptionPane.showMessageDialog和swing.utils.invokeAndWait的(事件调度)线程安全用法是什么?_Java_Swing_User Interface_Groovy_Event Dispatch Thread - Fatal编程技术网

Java JOptionPane.showMessageDialog和swing.utils.invokeAndWait的(事件调度)线程安全用法是什么?

Java JOptionPane.showMessageDialog和swing.utils.invokeAndWait的(事件调度)线程安全用法是什么?,java,swing,user-interface,groovy,event-dispatch-thread,Java,Swing,User Interface,Groovy,Event Dispatch Thread,我有一个简单的groovy脚本,它在执行的主线程中需要向用户显示一些对话框 我对swing的了解有限且陈旧,但我记得我读过一篇关于需要小心将GUI内容保留在事件调度线程(EDT)上的文章 如果我只是从我的主线程调用staticJOptionPane.showMessageDialog方法,那么我认为这会违反将GUI内容保留在EDT上的正确做法吗 我是否应该使用swing.utils.invokeAndWait方法,如下面的示例代码 void showHelloThereDialog()

我有一个简单的groovy脚本,它在执行的主线程中需要向用户显示一些对话框

我对swing的了解有限且陈旧,但我记得我读过一篇关于需要小心将GUI内容保留在事件调度线程(EDT)上的文章

如果我只是从我的主线程调用static
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完成后,除了消息对话框之外,上面没有做任何事情使来自其他对象的值可用

groovy“closures”实现Runnable这一事实可能会使代码比上面更简单


是否需要invokeAndWait?如果是这样,请给出一个正确实现的示例,以获得使用groovy的confirmDialog之类的结果?

这应该在EDT上,因此需要invokeAndWait或invokeLater。您可以看出,因为JOptionPane.showMessageDialog的代码最终创建和修改了Swing组件。从Java6开始,Sun说Swing组件的所有操作(无论它们是否已实现)都必须在EDT上完成


看看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");
}

JOptionPane
的showXXXDialog()之一的调用一直处于阻塞状态,直到用户选择ok/cancel/etc。通常情况下,您不会在事件调度线程(EDT)上放置这种缓慢的阻塞指令,因为其他每个GUI组件都将冻结。所以,本能地不把它放在EDT上是好的,但也是错的。原因正如其他一些人所说,该方法创建GUI组件,并且应该始终在EDT上完成。但是阻塞呢?您会注意到,即使您在EDT上运行它,它也可以正常工作。原因可以在源代码中找到。
JOptionPane
类创建一个对话框对象,然后调用
show()
,然后调用
dispose()。如果您阅读注释(或javadoc),您将看到它对方法的描述如下:

如果该对话框是模态的且不可见,则此调用将不显示 返回,直到通过调用hide或dispose隐藏对话框。它是 允许从事件分派线程显示模式对话框 因为工具箱将确保另一个事件泵在 调用此方法的用户被阻止


因此,在EDT上运行
JOptionPane
是完全安全的,尽管它被阻塞了。显然,在EDT之外调用Dialog的
show()
方法是安全的,但对于
JOptionPane
则不安全,因为它的方法是创建GUI组件、添加监听器、在模态时访问其他容器以及阻止对它们的输入,等等。您不希望所有这些都在EDT之外完成,因为它不是线程安全的,并且可能存在问题。诚然,我从未见过在EDT之外使用
JOptionPane
时出现问题,因此可能性似乎很低,但这是最有可能的。为对话框的容器传递一个null,并且只给字段提供不可变的对象(比如
String
s)作为参数,这将大大减少(据我所知,甚至可能会消除)由于所有相关GUI组件都是在同一个线程中创建和访问的,而它们不可见,因此可能会发生不好的情况。但是,你应该注意安全,把它放在EDT上。调用
SwingUtilities.invokeAndWait()

并不难,如果您正在编写Swing代码并使用Groovy,您应该查看Griffon。@Don感谢您的建议,我知道Griffon,它确实很有趣。另一方面,它的重量比我现在需要的要重得多,我也觉得在依赖这么多“魔法”之前,我想更好地理解一些细节。我真正了解的唯一文档是MEAP“狮鹫行动”。你知道它是否有用(或者其他来源是否有用)?