2011-12-01 35 views
4

我知道setVisible(false),dispose(),但他們不能真正關閉一個JDialog。當我有另一個線程停止時,JDialog的線程仍然運行。如何用Java代碼真正關閉一個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; 
     } 
    } 
} 

回答

10

發送使用dispatchEvent()JDialog一個WindowEvent.WINDOW_CLOSING事件,如圖herehere

附錄:System.exit()應小心使用,如討論herehere。在下面的例子中,即使在循環退出之前關閉對話框,第二個非守護線程也會正常完成。有關詳細信息,請參閱JLS §12.8 Program Exit

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(); 
    } 
} 
+0

@王先生:感謝您的跟進;我已經詳細闡述過了。 – trashgod