-2

可能的重复:
Java 中的 SwingWorker

我有几个需要一起工作的类,但它们不是。

一方面,我有主要:

public class Main
{

 public static void main(String[] args)
 {

  SwingUtilities.invokeLater(new Runnable()
  {

   @Override
   public void run()
   {

   //JFrame dummy for JDialog errors
   modal = new JFrame();

   new PrimaryErrorDialog("Title", "Message", e, false);

    JFrame masterWindow = new JFrame();
     masterWindow.setVisible();
   }
  }
 }
}

它创建 PrimaryErrorDialog 类:

private JDialog dialog = this;
private JTextArea text;
private JPanel buttonContainer;
private JButton sendErrorReportT, sendErrorReportF;

public PrimaryErrorDialog(String title, String message,
final Exception error, final boolean exit)
{
 super(Main.modal, title, true);

 //JButton for sending error report
 sendErrorReportT = new JButton("Send Error Report");
 sendErrorReportT.addActionListener(new ActionListener()
 {
  @Override
  public void actionPerformed(ActionEvent e)
  {
   dialog.dispose();

   dialog = new JDialog(Main.modal, "Sending...", true);

   Worker thread = new Worker(error);
   thread.start();

   JProgressBar progress = new JProgressBar();
   progress.setIndeterminate(true);

   dialog.add(progress);    
   dialog.pack();
   dialog.setVisible(true);
  }
 });

 //JButton for not sending error report
 sendErrorReportF = new JButton("Don't send error report");
 sendErrorReportF.addActionListener(new ActionListener()
 {
  @Override
  public void actionPerformed(ActionEvent e)
   {
    dialog.dispose();

    if (exit)
    {
     System.exit(0);
    }
   }
  });

 buttonContainer = new JPanel();
 buttonContainer.add(sendErrorReportT);
 buttonContainer.add(sendErrorReportF);

 add(text);
 add(buttonContainer);

 pack();
 setLocationRelativeTo(null);
 setVisible(true);
}

public void cleanUpAndContinue()
 {
  dialog.dispose();
  dialog = new JDialog(Main.modal, "title", true);
  dialog.add(/*Jbutton with listener that disposes this dialog*/)
  dialog.setVisible(true);
 }

它调用扩展 Thread 的 Worker 类:

public class Worker extends Thread
{
    Exception e;

    public Worker(Exception error)
    {
        e = error;
    }

    @Override
    public void run()
    {
    //do something that takes time
     PrimaryErrorDialog.cleanUpAndContinue();
    }

它返回到 PrimaryErrorDialog,然后它必须通知用户任务已完成,然后终止该对话框。

然后我们回到创建 masterWindow 的 main 。

所有这些代码都在创建 masterWindow 之前执行,因为该段在发生错误时运行(如果 LAF 不存在,.proprties 文件丢失等)...

这就是我创建虚拟 JFrame 的原因,所以 JDialog 可以附加到它,我不想让它成为 JFrame。

这段代码也稍后在程序中执行,对于“真正的”运行时错误,一些类只是有一点不同的参数和/或构造函数。

但是,这不起作用,我已经以百万种方式尝试过,我尝试使用 SwingWorker,似乎没有做我想做的事。通常甚至没有到达电子邮件代码,或者程序不等待对话框被释放......

而我想要什么?

发生错误。弹出对话框告诉我发生了错误并询问我是否要发送错误报告。我说不 - 对话框关闭,如果错误是致命的,则关闭整个程序。我说是的 - 对话框关闭,新的对话框打开,进度条不确定,而带有堆栈跟踪的电子邮件正在后台发送。电子邮件被发送,带有进度条的对话框关闭,并打开一个新的对话框,告诉我我的错误报告已发送。我按下 ok 并关闭对话框,如果错误是致命的,则删除整个程序,否则,继续从 Main 类离开的地方。

注意:任何类都可能发生错误,它不仅仅来自 Main...

4

2 回答 2

4

我没有读过你之前的问题,但是......

您遇到的基本问题是需要通知对话框(位于 EDT 内)后台线程已完成(并尽可能向用户提供反馈)。

在 Swing 中的并发课程中有所介绍。

下面是一个简单的概念证明。个人,我通常会构建一个自定义面板并将其放在 a 上JDialog,但这只是一个概念证明。

public class TestSwingWorker {

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {

                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                final JDialog dialog = new JDialog((Frame)null, "Happy, Happy, Joy, Joy", true);
                // This is so I can get my demo to work, you won't need it...
                dialog.addWindowListener(new WindowAdapter() {

                    @Override
                    public void windowClosing(WindowEvent e) {
                        System.exit(0);
                    }

                });

                JPanel panel = new JPanel(new GridBagLayout());
                panel.setBorder(new EmptyBorder(8, 8, 8, 8));
                dialog.setContentPane(panel);

                // You'll need you own icon...
                JLabel lblIcon = new JLabel(new ImageIcon(getClass().getResource("/waiting-64.png")));
                JLabel lblMessage = new JLabel("<html>Hard and work here<br>Please wait...</html>");
                final JProgressBar progressBar = new JProgressBar();

                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;
                gbc.anchor = GridBagConstraints.NORTH;
                gbc.weighty = 1;
                gbc.insets = new Insets(2, 2, 2, 2);
                gbc.gridheight = GridBagConstraints.REMAINDER;
                dialog.add(lblIcon, gbc);

                gbc.gridheight = 1;
                gbc.gridx = 1;
                gbc.gridy = 0;
                gbc.anchor = GridBagConstraints.WEST;
                gbc.weighty = 0;
                gbc.weightx = 1;
                dialog.add(lblMessage, gbc);

                gbc.gridy = 1;
                gbc.anchor = GridBagConstraints.NORTH;
                gbc.weighty = 1;
                dialog.add(progressBar, gbc);

                dialog.pack();
                dialog.setLocationRelativeTo(null);

                MyWorker worker = new MyWorker();
                // Get notification back from the worker...
                worker.addPropertyChangeListener(new PropertyChangeListener() {

                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {

                        MyWorker worker = (MyWorker) evt.getSource();
                        // Progress has been updated
                        if (evt.getPropertyName().equalsIgnoreCase("progress")) {

                            progressBar.setValue((Integer)evt.getNewValue());

                        // The state of the worker has changed...
                        } else if (evt.getPropertyName().equalsIgnoreCase("state")) {

                            if (worker.getState().equals(SwingWorker.StateValue.DONE)) {

                                dialog.dispose();

                            }

                        }

                    }
                });

                worker.execute();

                dialog.setVisible(true);

            }

        });

    }

    protected static class MyWorker extends SwingWorker<Object, Object> {

        @Override
        protected Object doInBackground() throws Exception {

            // My long running task...
            for (int index = 0; index < 100; index++) {

                // Change this to make it faster or slower...
                Thread.sleep(250);
                setProgress(index);

            }

            return null;

        }

    }

}
于 2012-09-28T21:25:10.210 回答
3
  • 肮脏的黑客包裹dialog.setVisible(true);invokeLater()

  • 使用SwingWorkerorRunnable#Thread代替 or 普通Thread

  • 是否存在您忽略答案的问题,尤其是您之前问题的评论

  • Swing Gui 不关心 Thread 的输出,因为没有为 Event Dispatch Thread 实现通知器,你必须通过 invokeLater 来调用它,或者使用SwingWorker,

  • SwingWorkers方法donepublish并且progress可以正确通知 EDT

于 2012-09-28T17:45:31.263 回答