围绕对话框的multithreading问题创建/销毁

可能重复:
Java中的SwingWorker

我有几个课程需要一起工作但是,他们不是。

首先,我有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类:

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

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

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

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

此代码也会在程序中执行,对于“实际”运行时错误,某些类只有一些不同的参数和/或构造函数。

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

我想要什么?

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

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

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

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

这在Swing中的Concurrency课程中有所介绍。

以下是一个简单的概念certificate。 个人,我通常会构建一个自定义面板并将其放到JDialog ,但这仅仅是一个概念validation。

 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("Hard and work here
Please wait..."); 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 { @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; } } }
  • 脏黑客包装dialog.setVisible(true); 进入invokeLater()

  • 使用SwingWorkerRunnable#Thread代替或使用普通Thread

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

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

  • SwingWorkers方法donepublishprogress可以正确通知EDT