java如何在非事件调度线程中间提示确认对话框
我有以下fun
将由非事件调度线程执行。在线程的中间,我想要一个
- 一个确认框弹出。线程暂停其执行李>
- 用户做出选择李>
- 线程将获得选择并继续执行李>
然而,我发现用线程安全的方式来实现这一点并不容易,因为对话框应该由事件调度线程来显示。我试着
public int fun()
{
// The following code will be executed by non event dispatching thread.
final int choice;
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
// Error.
choice = JOptionPane.showConfirmDialog(SaveToCloudJDialog.this, message, title, JOptionPane.YES_NO_OPTION);
}
});
return choice;
}
当然,这不会起作用,因为choice
是最终的,我无法将对话框返回的值分配给它
实现上述三个目标的正确方法是什么
# 1 楼答案
我有点厌倦了人们说事情是这样或那样的,但却不知道他们在说什么。我来这里想知道应该在哪个线程JOptionPane上运行,但我得到了相互矛盾的答案,没有真正的证据支持这两个观点。嗯,我自己研究过,我对这个答案很满意,所以我将与大家分享
在用户选择ok/cancel/etc之前,对JOptionPane的showXXXDialog()之一的调用一直处于阻塞状态。通常情况下,您不会在事件调度线程(EDT)上放置这种缓慢的阻塞指令,因为其他所有GUI组件都将冻结。所以,本能地不把它放在EDT上是好的,但这也是错误的。原因正如其他一些人所说,该方法创建GUI组件,这应该始终在EDT上完成。但是封锁呢?你会注意到,即使你在EDT上运行它,它也可以正常工作。原因可以在源代码中找到。JOptionPane类创建一个对话框对象,然后调用show()和dispose(),第一个是阻止线程的。如果您阅读了注释(或javadoc),您将看到它对该方法的描述:
因此,在EDT上运行JOptionPane是完全安全的,尽管它被阻塞了。显然,在EDT之外调用Dialog的show()方法是安全的,但在JOptionPane中情况并非如此,因为它的方法是创建GUI组件、添加侦听器、在模态时访问其他容器并阻止对它们的输入等。您不希望所有这些都在EDT之外完成,因为它不是线程安全的,而且可能存在问题。诚然,我从未见过在EDT之外使用JOptionPane时出现问题,因此可能性似乎很低,但这是最有可能的。为对话框的容器传递一个null,并且只给字段提供不可变的对象(比如字符串)作为参数,这将显著降低(甚至可能消除)发生错误的可能性,因为所有相关的GUI组件都是在同一个线程中创建和访问的,而它们是不可见的。但是,你应该注意安全,把它放在EDT上。称之为“勇气”并不难。invokeAndWait()
# 2 楼答案
从EDT启动JOptionPane,并通过FutureTask返回值
归功于杰塔伯恩 How to pass results from EDT back to a different thread?
# 3 楼答案
与流行的观点相反,你不需要分派到AWT(EventQueue)线程来显示对话框。那就展示出来吧
在执行JOptionPane时,showMessge()您的线程(thread.currentThread())将执行wait(),对话框将弹出。在showMessage之后使用结果,你就可以开始了
因此:
choice = JOptionPane.showConfirmDialog(this, message, title, JOptionPane.YES_NO_OPTION);
# 4 楼答案
# 5 楼答案
你试过:
# 6 楼答案
也许我不明白这个问题,但我也没有得到答案。。。如果希望调用线程阻止对fun()的调用,为什么要在一个新(并行)线程中显示JOptionPane?这还不够吗
PS如何定义非事件调度线程