我无法找到更好的方式在问题标题中表达问题,但希望您能理解......
我有以下代码......
[...]
final JDialog waitingDialog = optionPane.createDialog(optionPane, "Processing in backgroung");
waitingDialog.setLocationRelativeTo(homeFrame);
waitingDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
SwingWorker<Void, Void> backgroundThread = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
// Background processing is done here
System.out.println("[DEBUG] -- Background processing has started");
MyCustomClass.initParameters();
System.out.println("DEBUG] -- initParameters() has finished. Starting main processing now...");
waitingDialog.setVisible(true);
MyCustomClass.run();
return null;
}
// This is called when background thread above has completed
@Override
protected void done() {
waitingDialog.dispose();
};
};
backgroundThread.execute();
[and does other things after this...]
...执行得很好直到达到MyCustomClass.run()
。当它应该启动这种方法时,它根本就不会这样做。该应用程序不会暂停,停止或崩溃...它只是在后台处理完成后继续等待继续,这种情况不会发生。
MyCustomClass.run()
是在static
处的MyCustomClass
方法。我怀疑问题可能是它的名字 - 运行 - 所以我把它改成了一些随机的东西,如&#34; doIt()&#34;,但问题仍然存在。
该方法的第一行是一个简单的System.out.println("I got here")
,但即使是打印也没有。
我在方法调用之前和之后添加了断点并尝试调试,但这也没有帮助。一切似乎都很好,我无法找到问题。
修改
我问:如何在我希望它显示时才能显示对话框?换句话说,脚本是:
答案 0 :(得分:5)
立刻离开了蝙蝠,我发现你正在SwingWorker的doInBackground中进行Swing调用,这完全违背了使用SwingWorker或后台线程的目的。此外,您正在进行的通话,显示模式对话框:
waitingDialog.setVisible(true); // **** here ****
MyCustomClass.run(); // **** not sure what this does or if this makes Swing calls or not.
将暂停其下方的所有代码流,直到对话框不再可见,因为这是模态对话框的功能。这就是阻止你的SwingWorker的原因。您必须尝试分离代码,以便仅在Swing事件线程上进行Swing调用,并仅将worker用于后台工作。
相反
setVisible(true)
在伪代码中:
create modal dialog
create SwingWorker
Attach any PropertyChangeListeners to the SwingWorker (if needed)
Execute the SwingWorker
Display the modal dialog
因此,我在上面的代码中进行的第一次快速更改是从您的SwingWorker waitingDialog.setVisible(true);
方法中删除doInBackground()
,然后调用waitingDialog.setVisible(true);
方法 AFTER 执行SwingWorker,即在backgroundThread.execute()之后;特别是。我知道在让它显现之前调用dispose似乎是违反直觉的,但相信我,它会更好地运行,因为dispose调用将被运行所需的时间阻塞后台主题。
答案 1 :(得分:2)
首先,我接受了@Hovercraft Full Of Eels的回答,因为它确实帮助了我。就像我在评论中所说&#34; 简单地将SwinkWorker中的setVisible(true)替换为其定义之后,使程序按预期流动&#34;,这要归功于他的解释
但是,我需要更多一点(在原始问题的&#34;编辑&#34;部分中描述为脚本)。我设法通过以下代码实现了所需的行为......
final JOptionPane optionPane = new JOptionPane("<html>Please wait...<br>Initializing parameters</html>", JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION,
new ImageIcon(Home.class.getResource("/path/to/a/gif/loading.gif")), new Object[]{}, null);
final JDialog waitingDialog = optionPane.createDialog(optionPane, "MyApp");
waitingDialog.setLocationRelativeTo(homeFrame);
waitingDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
SwingWorker<Void, Void> backgroundThread1 = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
System.out.println("[DEBUG] -- Background processing of initParameters() has started");
MyCustomClass.initParameters();
System.out.println("[DEBUG] -- initParameters() has finished. Moving on...");
return null;
}
@Override
protected void done() {
waitingDialog.setVisible(false);
optionPane.setMessage("<html>Please wait... <br>Now working on your thing.</html>");
};
};
backgroundThread1.execute();
waitingDialog.setVisible(true);
SwingWorker<Void, Void> backgroundThread2 = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
System.out.println("[DEBUG] -- Start now the main processing in background");
MyCustomClass.run();
return null;
}
@Override
protected void done() {
waitingDialog.dispose();
};
};
backgroundThread2.execute();
waitingDialog.setVisible(true);
基本上(很明显)我所做的只是创建一个新的SwingWorker
并让每个例程在其中一个例程中运行。第一个完成后,它所做的只是隐藏(setVisible(false)
)&#34; waitingDialog&#34; - 所以主要线程没有被阻止 - 并且在第二个JOptionPane
开始后再次显示对话框时,更改对话框使用的SwingWorker
消息
我不知道这是否是一种好的,甚至是最好的/最聪明的方式,但它是有效的。如果有更好的方法,我会很高兴了解它。
我只有一个问题尚未解决。在MyCustomClass.run()
例程期间的某个地方,某个执行它的第二个SwingWorker
正被杀死/终止。
我怎么知道它正在发生?好吧,出于其他调试原因,我的例程中有一个循环在更新时打印某个值,然后突然停止打印(不,循环没有达到它的结束),&#34 ; waitingDialog&#34;消失,没有别的事情发生。该应用程序不会崩溃或任何事情。我可以继续使用它,好像什么也没发生过一样。没有抛出任何异常。
我不知道这是怎么发生的。任何帮助将不胜感激。
答案 2 :(得分:1)
众所周知,Swingworker会在后台线程中吞下运行时异常。您可以通过在Swingworker的done()方法中执行“get()”来检测它们。搜索“SimpleSwingWorker”,您将找到如何执行此操作的示例。