如何用Java代码真正关闭JDialog?

我知道setVisible(false)dispose() ,但它们无法真正关闭JDialog。 当我让另一个线程停止时,JDialog的线程仍在运行。

我不能使用System.exit(0) ,因为其他线程需要运行一段时间。

在代码之后,我最终在程序结束时通过System.exit(0)解决问题。

 public class CsUpdateCtrl { /** * 升级service */ private CsUpdateService service; private CsUpdateCtrl() { this.service = (CsUpdateService) RmiUtil.getBean(RmiUtil.Service.csupdate); } private static final Logger log = Logger.getLogger(CsUpdateCtrl.class.getName()); public static void main(String[] args) throws IOException { LogUtil.read(); log.info("进入自动更新系统"); CsUpdateCtrl ctrl = null; try { ctrl = new CsUpdateCtrl(); } catch (Exception e) { SwingUtil.lookAndFeel(); SwingUtil.message("无法连接服务器!"); log.info("无法连接服务器:" + e.getMessage()); return; } ctrl.start(ctrl.service.version()); } /** * 根据版本号判断是否更新,更新完毕则启动程序*/ private void start(int version) { PropertyIO io = new PropertyIO(); String oldVersion = io.get(PropertyKey.version); String serverAddress = io.get(PropertyKey.serverAddress); if (oldVersion == null || !oldVersion.equals(String.valueOf(version))) {// 版本号不相等,下载更新程序log.info("下载更新…"); DownLoad download1 = new DownLoad("http://" + serverAddress + "sdxg-csupdate/sdxg-csclient/sdxg-csclient.jar", "sdxg-csclient\\sdxg-csclient.jar"); Thread t1 = new Thread(download1); DownLoad download2 = new DownLoad("http://" + serverAddress + "sdxg-csupdate/sdxg-csclient/lib/sdxg-web.jar", "sdxg-csclient\\lib\\sdxg-web.jar"); Thread t2 = new Thread(download2); t1.start(); t2.start(); SwingUtil.lookAndFeel(); final DownloadView dialog = new DownloadView(new javax.swing.JFrame(), true); java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { dialog.setVisible(true); } }); // 结果判断// 若未完成,则不进行下一步while(!download1.result.finish() || !download2.result.finish()) { // do nothing } if(download1.result == Result.Complete && download2.result == Result.Complete) {// 更新完成// 版本号写入配置文件io.write(PropertyKey.version, String.valueOf(version)); // Nothing is usefull here, include dispose,dispatchEvent and so on // 启用应用程序log.info("启用应用程序"); this.runApp(); System.exit(0);// well, this is usefull } else {// 更新失败// Nothing is usefull here, include dispose,dispatchEvent and so on JOptionPane.showMessageDialog(null, "下载应用程序失败!"); log.info("下载应用程序失败!"); System.exit(0);// well, this is usefull } }else {// 版本号一样log.info("启用应用程序"); this.runApp(); } } /** * 运行客户端程序*/ private void runApp() { try { Runtime.getRuntime().exec("java -jar " + "sdxg-csclient\\sdxg-csclient.jar"); } catch (IOException ex) { JOptionPane.showMessageDialog(null, "启动应用程序失败!"); log.info(LogUtil.ex(ex, "启动应用程序失败!")); } } /** * 线程执行的结果*/ enum Result { Complete, UnComplete, Fail; public boolean finish() { return this != UnComplete; } } /** * 下载文件* @param urlName * @param fileName * @throws MalformedURLException * @throws IOException */ class DownLoad implements Runnable { private String urlName; private String fileName; Result result = Result.UnComplete; public DownLoad(String urlName, String fileName) { this.urlName = urlName; this.fileName = fileName; } @Override public void run() { try { URL url = new URL(urlName); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); InputStream is = connection.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); FileOutputStream fos = new FileOutputStream(fileName); int n = -1; while ((n = bis.read()) != -1) { fos.write(n); } fos.flush(); fos.close(); bis.close(); is.close(); result = Result.Complete; } catch (Exception ex) { result = Result.Fail; } } } 

使用dispatchEvent()JDialog发送一个WindowEvent.WINDOW_CLOSING事件,如此处和此处所示。

附录:应谨慎使用System.exit() ,如此处和此处所述 。 在下面的示例中,第二个非守护程序线程正常完成,即使对话框在其循环退出之前关闭也是如此。 有关详细信息,请参阅JLS§12.8程序退出

 import java.awt.EventQueue; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; /** * @see https://stackoverflow.com/questions/8336161 * @see https://stackoverflow.com/questions/6163606 */ public class DialogEventTest extends JDialog { public DialogEventTest() { this.setLayout(new GridLayout(0, 1)); this.add(new JLabel("Dialog event test.", JLabel.CENTER)); this.add(new JButton(new AbstractAction("Close") { @Override public void actionPerformed(ActionEvent e) { DialogEventTest.this.setVisible(false); DialogEventTest.this.dispatchEvent(new WindowEvent( DialogEventTest.this, WindowEvent.WINDOW_CLOSING)); } })); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.out.println(e.paramString()); } }); } private void display() { this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); this.pack(); this.setLocationRelativeTo(null); this.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new DialogEventTest().display(); } }); new Thread(new Runnable() { @Override public void run() { System.out.println("Starting…"); for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); System.out.println((i + 1) + "s. elapsed."); } catch (InterruptedException e) { e.printStackTrace(System.err); } } System.out.println("Finished."); } }).start(); } }