Java秋千等待消息不会出现
我有一个JAVA3D场景图更新任务,我的笔记本电脑需要3-4秒即可完成。在此期间,我希望一个窗口出现,要求用户等到作业完成。我有一个类似的情况,需要更长的时间,而我对摇摆工的实施则效果很好。但是,当我将代码应用于此更新操作时,对话框根本不会显示。
这是我想显示的waitdialog(我也尝试从jdialog继承 - 没有更改)
public class WaitDialog extends JFrame {
private static final long serialVersionUID = 1L;
protected int rows = 2;
protected int cols= 1;
protected int rowSpace= 12;
protected int colSpace= 12;
public WaitDialog(Component parent, String message) {
JPanel panel = new JPanel(new GridLayout(rows, cols, rowSpace, colSpace));
panel.setBorder( new EmptyBorder(12, 12, 12, 12) );
panel.add(new JLabel(message), BorderLayout.CENTER);
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
panel.add(progressBar);
setUndecorated(true);
setAlwaysOnTop(true);
getContentPane().add(panel);
pack();
setLocationRelativeTo(parent);
setVisible(true);
}
public void close() {
setVisible(false);
dispose();
}
}
使我头痛看起来像这样的方法...
public Result doIt(String fileName) throws Exception {
WaitDialog waitDialog = new WaitDialog(null, "Update...");
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
Result result = ansicht.calculateResult(inputStream); // Java3D calculation
waitDialog.close();
return result;
}
在此版本中,未显示waitdialog,但calculteresult效果很好。 因此,如上所述,我从另一个地方复制了工作逻辑,看起来像这样……
public Result doIt(String fileName) throws Exception {
WaitDialog waitDialog = new WaitDialog(null, "Update...");
SwingWorker<Result,Void> worker = new SwingWorker<Result,Void>() {
@Override
protected Result doInBackground() throws Exception {
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
Result result = ansicht.calculateResult(inputStream); // Java3D calculation
return result;
}
@Override
protected void done() {
waitDialog.close();
}
};
worker.execute();
Result result = worker.get();
return result;
}
没有效果。没有显示的消息,计算菌都可以正常工作。 因此,我在网络上查看了我可能拥有的选择,并尝试了这一点...
public Result doIt(String fileName) throws Exception {
WaitDialog waitDialog = new WaitDialog(null, "Update...");
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
SwingUtilities.invokeAndWait(() -> {
try {
result = ansicht.calculateResult(inputStream); // Java3D calculation
} catch (Exception e) {
e.printStackTrace();
}
});
waitDialog.close();
return result;
}
结果现在是类变量。此版本显示了“等待对话框”,但是计算器呼叫没有回来,对话框不会消失。
我还尝试了一个带有老式线程的版本,我在网络中找到了它……
public Result doIt(String fileName) throws Exception {
WaitDialog waitDialog = new WaitDialog(null, "Update...");
Thread thread = new Thread(() -> {
SwingUtilities.invokeAndWait(() -> {
try {
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
result = ansicht.calculateResult(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
});
} catch (Exception e) {
e.printStackTrace();
}
});
thread.start();
while(thread.isAlive()) {};
waitDialog.close();
return result;
}
也没有做我想做的事情。
您能告诉我如何做吗?先感谢您。
I have a Java3D scenegraph update task which takes 3-4 seconds on my laptop to complete. During this time I want a window showing up, asking the user to wait until the job completes. I have a simelar situation which takes longer and my implementation with a SwingWorker works fine. But when I apply the code to this update operation the dialog doesn't show up at all.
Here is the WaitDialog which I want to show (I also tried to inherit from JDialog - no change)
public class WaitDialog extends JFrame {
private static final long serialVersionUID = 1L;
protected int rows = 2;
protected int cols= 1;
protected int rowSpace= 12;
protected int colSpace= 12;
public WaitDialog(Component parent, String message) {
JPanel panel = new JPanel(new GridLayout(rows, cols, rowSpace, colSpace));
panel.setBorder( new EmptyBorder(12, 12, 12, 12) );
panel.add(new JLabel(message), BorderLayout.CENTER);
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
panel.add(progressBar);
setUndecorated(true);
setAlwaysOnTop(true);
getContentPane().add(panel);
pack();
setLocationRelativeTo(parent);
setVisible(true);
}
public void close() {
setVisible(false);
dispose();
}
}
The method that gives me headache looks like this...
public Result doIt(String fileName) throws Exception {
WaitDialog waitDialog = new WaitDialog(null, "Update...");
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
Result result = ansicht.calculateResult(inputStream); // Java3D calculation
waitDialog.close();
return result;
}
In this version, the waitDialog is not shown but calculteResult works fine.
Therefore, as indicate above, I copied the working logic from another place, which looks like this...
public Result doIt(String fileName) throws Exception {
WaitDialog waitDialog = new WaitDialog(null, "Update...");
SwingWorker<Result,Void> worker = new SwingWorker<Result,Void>() {
@Override
protected Result doInBackground() throws Exception {
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
Result result = ansicht.calculateResult(inputStream); // Java3D calculation
return result;
}
@Override
protected void done() {
waitDialog.close();
}
};
worker.execute();
Result result = worker.get();
return result;
}
which shows no effect. No message shown and calculateResult works still fine.
So I looked in the web what alternatives I might have and tried this...
public Result doIt(String fileName) throws Exception {
WaitDialog waitDialog = new WaitDialog(null, "Update...");
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
SwingUtilities.invokeAndWait(() -> {
try {
result = ansicht.calculateResult(inputStream); // Java3D calculation
} catch (Exception e) {
e.printStackTrace();
}
});
waitDialog.close();
return result;
}
result being now a Class variable. This version shows the wait dialog, but the calculateResult call is not coming back and the dialog doesn't disappear.
I also tried a version with an old fashioned Thread, which I found in the web...
public Result doIt(String fileName) throws Exception {
WaitDialog waitDialog = new WaitDialog(null, "Update...");
Thread thread = new Thread(() -> {
SwingUtilities.invokeAndWait(() -> {
try {
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
result = ansicht.calculateResult(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
});
} catch (Exception e) {
e.printStackTrace();
}
});
thread.start();
while(thread.isAlive()) {};
waitDialog.close();
return result;
}
also not doing what I want.
Can you please advise me how to do this? Thank you in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Swing的工作方式是您拥有不断运行和处理GUI事件的事件调度线程(EDT)。当您执行长期运行任务时,您将其运行在其他线程上,然后告诉EDT您已经完成。
在EDT上被称为“ DOIT”吗?我要假设是。
您的所有版本都会阻止“ DOIT”,直到结果完成后。您需要让DOIT完成。我建议回电。
然后,在第二版中,您可以更新它。
这是您的代码最糟糕的版本。
您实际上是将长期运行的任务发布到EDT并阻止当前线程,我怀疑这也是EDT。
The way swing works is you have the Event Dispatch Thread (EDT) that is constantly running and processing GUI events. When you have a long running task, you run it on a different thread, then tell the EDT that your are finished.
Is "doIt" being called on the EDT? eg did you start it from an event like a button? I am going to assume it is.
All of your versions are blocking "doIt" until after the result is finished. You need to let doIt finish. I would suggest a call back.
Then in second version you can update it.
This is the worst version of your code.
That you are literally posting your long running task to the EDT and blocking the current thread, which I suspect is also the EDT.
除了(希望支持)马特的回答。
秋千不是线程,也不是单线线程,这意味着您应该尝试从事件派遣线程或执行长期运行或从上下文中更新UI的状态(或UI所依赖的任何内容)事件派遣线程的内容。
参见 Swing 同意的同意。
这里的重要一点是
swingworker#get
方法。 Javadocs州:这对解释您的问题将有很长的路要走。
以下是另一种可能的方法。它利用专用
swingworker
...,并通过使用
property> propertyChangelistener
...并使用观察者(又称听众)来通知呼叫者操作完成或失败,以便感兴趣的方可以处理操作的结果。
重要的是要注意,这只是您可以实现这一目标的一种方式,而Matt的解决方案也是有效的解决方案!
可运行的示例...
In addition to (and hopefully supporting) matt's answer.
Swing is not thread and is single threaded, this means that you should try and update the state of the UI (or anything the UI relies on) from outside the context of the Event Dispatching Thread or execute long running or blocking operations from within the context of the Event Dispatching Thread.
See Concurrency in Swing for more details.
The important point here is the
SwingWorker#get
method. The JavaDocs state:This would go a long way to explaining your issue.
The following is another possible approach. It makes use of dedicated
SwingWorker
...and is monitored through the use of
PropertyChangeListener
...and makes use of an observer (AKA listener) to notify the caller that the operation completed or failed, so that the interested party can deal with the result of the operation.
It's important to note that this is just one way you might achieve this and matt's solution is also a valid solution!
Runnable example...