我有以下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
是最终的,我无法将对话框中返回的值分配给它。
实现上述3个目标的正确方法是什么?
答案 0 :(得分:5)
你试过了吗?
public int fun()
{
// The following code will be executed by non event dispatching thread.
final int[] choice = new int[1];
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
// Error.
choice[0] = JOptionPane.showConfirmDialog(SaveToCloudJDialog.this, message, title, JOptionPane.YES_NO_OPTION);
}
});
return choice[0];
}
答案 1 :(得分:2)
public int fun() throws InterruptedException, InvocationTargetException {
// The following code will be executed by non event dispatching thread.
ChoiceRunnable runabble = new ChoiceRunnable();
SwingUtilities.invokeAndWait(runabble);
return runabble.choice;
}
class ChoiceRunnable implements Runnable {
private int choice;
public void run() {
choice = JOptionPane.showConfirmDialog(SaveToCloudJDialog.this, message, title, JOptionPane.YES_NO_OPTION);
}
}
答案 2 :(得分:2)
与流行的看法相反,您不需要调度到AWT(EventQueue)线程来显示对话框。所以只是展示它。
当您执行JOptionPane时,showMessge()您的线程(Thread.currentThread())将执行wait(),并且会弹出对话框。在showMessage之后使用结果,你就可以了。
因此:
choice = JOptionPane.showConfirmDialog(this, message, title, JOptionPane.YES_NO_OPTION);
答案 3 :(得分:1)
可能是我不明白这个问题,但是我也没有得到答案...如果你想让调用线程阻塞对fun()的调用,为什么要在一个新的(并行)线程中显示JOptionPane ?这不应该足够吗?
public int fun() {
return JOptionPane.showConfirmDialog(null, message, title, JOptionPane.YES_NO_OPTION);
}
PS如何定义非事件调度线程?
答案 4 :(得分:1)
我有些厌倦了人们说事情是这样或那样的,但实际上并不知道他们在谈论什么。我来到这里想知道应该运行哪个线程JOptionPane但是我得到了相互矛盾的答案,没有真正的证据支持任何一点。好吧,我自己研究过,我对这个答案很满意,所以我会分享。
对一个JOptionPane的showXXXDialog()的调用是BLOCKING,直到用户选择ok / cancel / etc.通常,您不会在事件调度线程(EDT)上放置这种缓慢阻塞的指令,因为每个其他GUI组件都会冻结。所以,直觉不要把它放在EDT上是好的,但这也是错误的。原因如其他一些人所述,该方法创建GUI组件,这应始终在EDT上完成。但阻止怎么样?您会注意到,即使您在EDT上运行它,它也能正常工作。原因在源代码中找到。 JOptionPane类创建一个Dialog对象,然后调用show(),然后调用dispose(),第一个是阻塞线程。如果您阅读了评论(或javadoc),您会看到它说明了这个方法:
如果对话框是模态的并且尚未显示,则此调用不会 返回,直到通过调用hide或dispose隐藏对话框。它是 允许从事件调度线程显示模态对话框 因为工具包将确保另一个事件泵运行时 调用此方法的一个被阻止。
因此,尽管它阻塞了,但在EDT上运行JOptionPane是完全安全的。显然,从EDT调用Dialog的show()方法是安全的,但是对于JOptionPane也是如此,因为它的方法是创建GUI组件,添加监听器,在模态时访问其他容器并阻止对它们的输入等。你不是希望所有这些都在EDT之外完成,因为它不是线程安全的,并且可能存在问题。不可否认,在EDT上使用JOptionPane时我从来没有遇到过问题,因此机会似乎很低,但它们肯定是可能的。为对话框的容器传入一个null并且只给出不可变对象(比如字符串)作为字段的参数将显着减少(甚至可能消除据我所知)发生错误的可能性,因为所有相关的GUI组件都是并且在它们不可见时在同一个线程中访问。但是,你应该安全并把它放在EDT上。调用SwingUtilities.invokeAndWait()并不困难。
答案 5 :(得分:0)
从EDT启动JOptionPane,并使用FutureTask传回值。
))))
归功于jtahlborn How to pass results from EDT back to a different thread?