在我的申请中,我想做类似
的事情SwingWorker.done()
,执行我的其余代码)我开始注意到问题:我的new WaitScreen().execute();
之后的代码正在执行之前我必须手动关闭对话框以触发{{1 }}。
为了弄清楚它,我采取了一些simpler code,使它成为我自己的,并用它来模仿我的问题。这是:
import java.awt.EventQueue; import java.awt.BorderLayout;
done()
当只有import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class SwingWorkerDialogTest
{
public static void main(String[] args)
{
new SwingWorkerDialogTest();
}
private JDialog dialog;
public SwingWorkerDialogTest()
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex)
{
}
catch (javax.swing.UnsupportedLookAndFeelException ex)
{
}
MyWorker worker = new MyWorker(true);
worker.execute();
new MyWorker(false).execute();
}
});
}
public class MyWorker extends SwingWorker<Object, Object>
{
private boolean runGUI;
public MyWorker(boolean b) { this.runGUI = b; }
@Override
protected Object doInBackground() throws Exception
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
if (runGUI)
{
getDialog().setVisible(true);
}
else
{
for (int j = 0; j < 30; j++)
{
System.out.println("j == " + j);
}
}
}
});
Thread.sleep(20000);
return null;
}
@Override
protected void done()
{
System.out.println("now in done...");
JDialog dialog = getDialog();
// Don't care, dismiss the dialog
//dialog.setVisible(false);
dialog.dispose();
}
}
protected JDialog getDialog()
{
if (dialog == null)
{
dialog = new JDialog();
dialog.setModal(true);
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setLayout(new BorderLayout());
dialog.add(new JLabel("Please wait..."));
dialog.setSize(200, 200);
dialog.setLocationRelativeTo(null);
}
return dialog;
}
}
正在运行时,它工作正常。但是,在worker
另一个execute()
的那一刻,我的问题又重新出现了。我该如何解决这个问题?
答案 0 :(得分:1)
因此,SwingWorker
的要点是允许您在事件调度线程的上下文之外的后台线程中执行长时间运行/阻塞任务,因此您不会阻止UI。 / p>
新的WaitScreen()之后的代码.execute();正在执行之前我必须手动关闭对话框以触发done()
是的,这是预期的,这是SwingWorker
的重点。发生的事情是,当你调用execute时,一个新的Thread
是创建的,在某个时候是未来,它会(间接地)调用你的doInBackground
方法,同时调用所有其他线程(比如EDT)被允许继续。
在SwingUtilities.invokeLater
中使用SwingWorker
也是毫无意义的,工作人员旨在提供功能,以便将更新发送回EDT。
好的,在你的情况下,一个简单的解决方案是先调用execute
然后立即显示对话框,从而阻止代码执行,例如......
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class SwingWorkerDialogTest {
public static void main(String[] args) {
new SwingWorkerDialogTest();
}
private JDialog dialog;
public SwingWorkerDialogTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
}
MyWorker worker = new MyWorker(true);
worker.execute();
new MyWorker(false).makeItSo();
System.out.println("I'm free !");
}
});
}
public class MyWorker extends SwingWorker<Object, Object> {
private boolean runGUI;
public MyWorker(boolean b) {
this.runGUI = b;
}
public void makeItSo() {
execute();
getDialog().setVisible(true);
}
@Override
protected Object doInBackground() throws Exception {
for (int j = 0; j < 30; j++) {
System.out.println("j == " + j);
Thread.sleep(10);
}
Thread.sleep(20000);
return null;
}
@Override
protected void done() {
System.out.println("now in done...");
JDialog dialog = getDialog();
// Don't care, dismiss the dialog
//dialog.setVisible(false);
dialog.dispose();
}
}
protected JDialog getDialog() {
if (dialog == null) {
dialog = new JDialog();
dialog.setModal(true);
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setLayout(new BorderLayout());
dialog.add(new JLabel("Please wait..."));
dialog.setSize(200, 200);
dialog.setLocationRelativeTo(null);
}
return dialog;
}
}