Swing around dialog create / destroy的多线程问题 [英] Multithreading issues with Swing around dialog create/destroy

查看:88
本文介绍了Swing around dialog create / destroy的多线程问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

Java中的SwingWorker

我有几个需要协同工作的课程,但是,他们不是。

I have several classes that need to work together but, they're not.

首先,我有Main:

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类:

It creates PrimaryErrorDialog class:

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);
 }

它调用扩展线程的工作者类:

It calls thw Worker class that extends Thread:

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,然后必须通知用户该任务已完成,然后终止该对话框。

It goes back to PrimaryErrorDialog, which would then have to inform the user that task was completed, and then terminate that dialog.

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

Then we go back to main where masterWindow is created.

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

All of this code is executed prior to creation of masterWindow, because this segment is ran when an error occurrs (if LAF is not present, .proprties files are missing, etc)...

这就是为什么我创建了虚拟JFrame,所以JDialog可以附加到它,我不想把它变成JFrame。

That's why I created the dummy JFrame, so JDialog can attach to it, I didn't wan't to make it a JFrame.

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

This code is also executed later in program, for "real" runtime errors, some classes just have a bit different parameters and/or constructors.

然而,这不起作用,我有尝试用数百万种方式,我尝试使用SwingWorker,似乎什么也没做我想要的。通常甚至没有达到电子邮件代码,或者程序没有等待处理对话框......

However, this does not work, I have tried it in milion ways, i tried with SwingWorker, nothing seems to do what I want. Usually the email code is not even reached, or program doesn't wait for the dialogs to be disposed...

我想要什么?

发生错误。
对话框弹出告诉我发生错误并询问我是否要发送错误报告。
我说没有 - 对话关闭,如果错误是致命的话,取消整个程序。
我说是 - 对话框关闭,新的打开时带有不确定的进度条,WHILE带有stacktrace的电子邮件正在后台发送。
发送电子邮件,关闭进度条的对话框,打开一个新电子邮件,告诉我发送了错误报告。
我按下ok并关闭对话框,如果错误是致命的话,取下整个程序,否则,继续从Main类离开它。

Error occurrs. Dialog pops up telling me an error occurred and asking me if I want to send an error report. I say no - dialog closes, taking down the whole program if error is fatal. I say yes - dialog closes, new one opens with indetermined progressbar, WHILE email with stacktrace is being sent in the background. Email gets sent, dialog with progressbar closes and a new one opens telling my my error report was sent. I press ok and dialog closes, taking down the whole program if error is fatal, else, continues where it left of from Main class.

注意:错误可能在任何类中出现,它不是仅来自Main ...

Note: An error can occurr in any class, it doesn't be from Main only...

推荐答案

我没看过你然而,上一个问题...

I've not read you're previous question, however...

你遇到的基本问题是需要通知后台线程已经完成的对话框(在EDT中)(以及如果可能的话,向用户提供反馈。)

The basic problem you have is needing to notify the dialog (which is within the EDT) that the background thread has completed (as well as provide feedback to the user if possible).

这包含在 Swing中的并发性课程。

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

Below is a simple proof of concept. Personal, I would normally construct a custom panel and put it onto the a JDialog, but this just a proof of concept.

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;

        }

    }

}

这篇关于Swing around dialog create / destroy的多线程问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆