Java Swing-around对话框创建/销毁的多线程问题

Java Swing-around对话框创建/销毁的多线程问题,java,multithreading,swing,jdialog,event-dispatch-thread,Java,Multithreading,Swing,Jdialog,Event Dispatch Thread,可能重复: 我有几个课程需要一起学习,但它们不是 首先,我有几个主要问题: public class Main { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { //JFrame dummy for JDialog errors modal = new JFram

可能重复:

我有几个课程需要一起学习,但它们不是

首先,我有几个主要问题:

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);
 }
它调用扩展线程的thw 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,然后PrimaryErrorDialog必须通知用户任务已完成,然后终止该对话框

然后我们回到主窗口,主窗口就是在这里创建的

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

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

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

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

我想要什么

错误时有发生。 对话框弹出,告诉我发生了错误,并询问我是否要发送错误报告。 我说否-对话框关闭,如果错误是致命的,则关闭整个程序。 我说是-对话框关闭,新对话框打开时带有未确定的progressbar,而带有stacktrace的电子邮件在后台发送。 发送电子邮件后,progressbar对话框关闭,并打开一个新对话框,告知我的错误报告已发送。 我按下ok,对话框关闭,如果错误是致命的,则关闭整个程序,否则,继续从主类离开的地方

注意:错误可能发生在任何类中,它不仅仅来自Main…

  • 脏的hack wrap
    dialog.setVisible(true)进入
    invokeLater()

  • 使用
    SwingWorker
    Runnable#Thread
    代替或普通
    Thread

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

  • Swing Gui不关心线程的输出,因为没有为事件分派线程实现通知程序,您必须通过invokeLater调用它,或者使用
    SwingWorker

  • SwingWorkers
    方法
    完成
    发布
    进度
    可以正确通知EDT


我还没有读到你之前的问题,但是

您面临的基本问题是需要通知对话框(位于EDT内)后台线程已完成(如果可能,还需要向用户提供反馈)

本课将介绍这一点

下面是一个简单的概念证明。就个人而言,我通常会构造一个自定义面板,并将其放在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;

        }

    }

}
公共类TestSwingWorker{
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}捕获(ClassNotFoundException ex){
}catch(实例化异常){
}捕获(非法访问例外){
}捕获(无支持的LookandFeelexception ex){
}
final JDialog dialog=newjdialog((Frame)null,“Happy,Happy,Joy,Joy”,true);
//这是我可以让我的演示工作,你不会需要它。。。
addWindowListener(新的WindowAdapter(){
@凌驾
公共无效窗口关闭(WindowEvent e){
系统出口(0);
}
});
JPanel panel=newjpanel(newgridbagloayout());
专家组命令(新的清空命令(8,8,8,8));
对话框.setContentPane(面板);
//你需要你自己的图标。。。
JLabel lblIcon=newjlabel(newimageicon(getClass().getResource(“/waiting-64.png”));
JLabel lblMessage=新JLabel(“在这里努力工作,请稍候…”);
最终JProgressBar progressBar=新JProgressBar();
GridBagConstraints gbc=新的GridBagConstraints();
gbc.gridx=0;
gbc.gridy=0;
gbc.anchor=gridbag.NORTH;
gbc.weighty=1;
gbc.插图=新插图(2,2,2,2);
gbc.gridheight=GridBagConstraints.rements;
对话框.添加(lblIcon,gbc);
gbc.gridheight=1;
gbc.gridx=1;
gbc.gridy=0;
gbc.anchor=GridBagConstraints.WEST;
gbc.weighty=0;
gbc.weightx=1;
添加(LBL消息,gbc);
gbc.gridy=1;
gbc.anchor=gridbag.NORTH;
gbc.weighty=1;
添加(进度条,gbc);
dialog.pack();
对话框.setLocationRelativeTo(空);
MyWorker=新的MyWorker();
//从工作人员处获取通知。。。
worker.addPropertyChangeListener(新的PropertyChangeListener(){
@凌驾
公共作废属性更改(属性更改事件evt){
MyWorker=(MyWorker)evt.getSource();
//已更新进展情况
if(evt.getPropertyName().equalsIgnoreCase(“进度”)){
progressBar.setValue((整数)evt.getNewValue());
//工人的状态已更改。。。
}否则,如果(ev)