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

发布于 2024-10-28 03:25:56 字数 764 浏览 2 评论 0原文

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

我的挥杆知识有限且生疏,但我记得读过关于需要小心地将 GUI 内容保留在事件分派线程 (EDT) 上的内容。

如果我只是从主线程调用静态 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“闭包”实现 Runnable 的事实将使代码比上面更简单。

是否需要调用AndWait?如果是这样,有人可以给出一个正确实现的例子,以获得像使用groovy的confirmDialog这样的结果吗?

I have a simple groovy script that from its main thread of execution needs to display some dialog boxes to the user.

My swing knowledge is limited and rusty but I recall reading about the need to be careful to keep GUI stuff on the event-dispatching thread (EDT).

If I just call the static JOptionPane.showMessageDialog method from my main thread am I right in assuming this would violate the correct practice of keeping GUI stuff on the EDT?

Should I actually be using the swing.utils.invokeAndWait method such as in the following example code?


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

Now the above doesn't do anything to make values from something other than a message dialog available after invokeAndWait completes.

Presumably the fact that groovy 'closures' implement Runnable will make for simpler code than above.

Is invokeAndWait required? And if so would someone please give an example of correct implementation to get the result of something like a confirmDialog using groovy?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

怂人 2024-11-04 03:25:56

对 JOptionPane 的 showXXXDialog() 之一的调用将被阻塞,直到用户选择“确定”/“取消”等。一般来说,您通常不会将如此缓慢的阻塞指令放在事件调度线程 (EDT) 上,因为每个其他 GUI 组件都会冻结。因此,不把它放在 EDT 上的直觉是好的,但也是错误的。原因如其他一些人所述,该方法创建 GUI 组件,并且这应该始终在 EDT 上完成。但是阻塞又如何呢?您会注意到,即使您在 EDT 上运行它,它也能正常工作。原因在源码中找到。 JOptionPane 类创建一个 Dialog 对象,然后调用 show(),然后调用 dispose(),其中第一个调用会阻塞线程。如果您阅读注释(或 javadoc),您将看到它是关于该方法的:

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

因此,尽管 JOptionPane 会阻塞,但在 EDT 上运行 JOptionPane 是完全安全的。显然,在 EDT 之外调用 Dialog 的 show() 方法是安全的,但对于 JOptionPane 则不然,因为它的方法是创建 GUI 组件、添加侦听器、访问其他组件您不希望所有这些都在 EDT 之外完成,因为它不是线程安全的,并且可能会出现问题。诚然,我在 EDT 之外使用 JOptionPane 时从未遇到过问题,因此可能性似乎很低,但它们肯定是有可能的。为对话框的容器传递 null 并仅将不可变对象(例如 String )作为字段的参数将显着减少(据我所知甚至可能消除)出现不良情况的可能性发生这种情况是因为所有相关的 GUI 组件都是在同一个线程中创建和访问的,而它们是不可见的。但是,为了安全起见,您应该将其放在 EDT 上。调用 SwingUtilities.invokeAndWait() 并不困难。

A call to one of JOptionPane's showXXXDialog() is BLOCKING until the user selects ok/cancel/etc. In general you do not put such slow blocking insturctions on the Event Dispatch Thread (EDT) as a rule because every single other GUI component will freeze. So, a gut instinct to not put it on the EDT is good, but it is also wrong. The reason is as stated by some others, the method creates GUI components and this should always be done on the EDT. But what about the blocking? You will notice that even if you do run it on the EDT, it works fine. The reason is found inside the source code. The JOptionPane class creates a Dialog object and then calls show() followed by dispose(), the first of which is what blocks the thread. If you read the comments (or javadoc), you will see that it says this about the method:

If the dialog is modal and is not already visible, this call will not
return until the dialog is hidden by calling hide or dispose. It is
permissible to show modal dialogs from the event dispatching thread
because the toolkit will ensure that another event pump runs while the
one which invoked this method is blocked.

So, it is perfectly safe to run JOptionPane on the EDT despite it blocking. Obviously, it is safe to call Dialog's show() method off the EDT but the same is not true for JOptionPane because its methods are creating GUI components, adding listeners, accessing other containers when modal and blocking input to them, etc. You do not want all of this done off the EDT because it is not thread-safe and there could be problems. Admittedly, I have never seen problems when using JOptionPane off the EDT and so the chances seem low, but they are most certainly possible. Passing in a null for the container of the dialog and only giving immutable objects (like Strings) as arguments to the fields will significantly reduce (maybe even eliminate as far as I know) the chance of something bad happening because all relevant GUI components are made and accessed within the same thread while they are not visible. But, you should just be safe and put it on the EDT. It is not that difficult to call SwingUtilities.invokeAndWait().

蝶舞 2024-11-04 03:25:56

这应该在 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

This should be on the EDT so invokeAndWait, or invokeLater, are required. You can tell since the code for JOptionPane.showMessageDialog eventually creates and modifies Swing components. As of Java 6, Sun says that all manipulations of Swing components (whether they have been realized or not) must be done on the 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

够钟 2024-11-04 03:25:56

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

Take a look at groovy.swing.SwingBuilder, it encapsulates invokeAndWait and invokeLater. Your example can be written as:

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");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文