在SwingWorker.execute()之后执行代码......在

时间:2015-10-29 05:18:26

标签: java multithreading swingworker

在我的申请中,我想做类似

的事情
  • 显示等待对话框,其中一些准备任务正在后台进行
  • 完成准备任务后,关闭对话框
  • 关闭对话框(或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()的那一刻,我的问题又重新出现了。我该如何解决这个问题?

1 个答案:

答案 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;
    }

}