<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Swing


    天行健 君子以自強不息

    posts - 69, comments - 215, trackbacks - 0, articles - 16
       :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    SwingUtilities中invokeLater和invokeAndWait的介紹

    Posted on 2007-07-10 14:28 zht 閱讀(12598) 評論(0)  編輯  收藏 所屬分類: Swing

    SwingUtilities中invokeLater和invokeAndWait介紹
       在Java中Swing是線程不安全的,是單線程的設計,這樣的造成結果就是:只能從事件派發線程訪問將要在屏幕上繪制的Swing組件。事件派發線程是調用paint和update等回調方法的線程,它還是事件監聽器接口中定義的事件處理方法,例如,ActionListener中的actionPerformed方法在事件派發線程中調用。
       Swing是事件驅動的,所以在回調函數中更新可見的GUI是很自然的事情,比如,有一個按鈕被按下,項目列表需要更新時,則通常在與該按鈕相關聯的事件監聽器的actionPerformed方法中來實現該列表的更新,從事件派發線程以外的線程中更新Swing組件是不正常的。
       有時需要從事件派發線程以外的線程中更新Swing組件,例如,在actionPerformed中有很費時的操作,需要很長時間才能返回,按鈕激活后需要很長時間才能看到更新的列表,按鈕會長時間保持按下的狀態只到actionPerformed返回,一般說來耗時的操作不應該在事件處理方法中執行,因為事件處理返回之前,其他事件是不能觸發的,界面類似于卡住的狀況,所以在獨立的線程上執行比較耗時的操作可能更好,這會立即更新用戶界面和釋放事件派發線程去派發其他的事件。
       SwingUtilities類提供了兩個方法:invokeLate和invoteAndWait,它們都使事件派發線程上的可運行對象排隊。當可運行對象排在事件派發隊列的隊首時,就調用其run方法。其效果是允許事件派發線程調用另一個線程中的任意一個代碼塊。
       只有從事件派發線程才能更新組件。
       程序示例:更新組件的錯誤方法
       startButton.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent e) {
        GetInfoThread t = new GetInfoThread(Test.this);
        t.start();
        startButton.setEnabled(false);
       }
      });
      
      class GetInfoThread extends Thread {
     Test applet;

     public GetInfoThread(Test applet) {
      this.applet = applet;
     }

      public void run() {
       while (true) {
        try {
         Thread.sleep(500);
         applet.getProgressBar().setValue(Math.random() * 100);
        } catch (InterruptedException e) {
         e.printStackTrace();
        }
       }
      }
     }
     錯誤分析:在actionPerformed中,監聽器把按鈕的允許狀態設置為false,由于是在事件派發線程上調用actionPerformed,所以setEnabled是一個有效的操作,但是在GetInfoThread中設置進度條是一個危險的做法,因為事件派發線程以外的線程更新了進度條,所以運行是不正常的。

       1、invokeLater使用
        class GetInfoThread extends Thread {
      Test applet;
     
      Runnable runx;
     
      int value;

      public GetInfoThread(final Test applet) {
       this.applet = applet;
       runx = new Runnable() {
        public void run() {
         JProgressBar jpb = applet.getProgressBar();
         jpb.setValue(value);
        }
       };
      }

       public void run() {
        while (true) {
         try {
          Thread.sleep(500);
          value = (int) (Math.random() * 100);
          System.out.println(value);
          SwingUtilities.invokeLater(runx);
         } catch (InterruptedException e) {
          e.printStackTrace();
         }
        }
       }
      }
       
       2、invokeAndWait
       與invoikeLater一樣,invokeAndWait也把可運行對象排入事件派發線程的隊列中,invokeLater在把可運行的對象放入隊列后就返回,而invokeAndWait一直等待知道已啟動了可運行的run方法才返回。如果一個操作在另外一個操作執行之前必須從一個組件獲得信息,則invokeAndWait方法是很有用的。
       class GetInfoThread extends Thread {
       Runnable getValue,setValue;
       int value,currentValue;
       public GetInfoThread(final Test applet){
       getValue=new Runnable(){
       public void run(){
        JProgressBar pb=applet.getProgressBar();
        currentValue=pb.getValue();
        }
       };
       setValue=new Runnable(){
        public void run(){
         JProgressBar pb=applet.getProgressBar();
         pb.setValue(value);
        }
       }
       }
       public void run(){
        while(true){
        try{
        Thread.currentThead().sleep(500);
        value=(int)(Math.random()*100);
        try{
        SwingUtilities.invokeAndWait(getValue);//直到getValue可運行的run方法返回后才返回
          }catch(Exception ex){
          }
          if(currentValue!=value){
          SwingUtilities.invokeLater(setValue);
          }
         }
         }catch(Exception ex){
          }
        }
       }
       invokeLater和invoikeAndWait的一個重要區別:可以從事件派發線程中調用invokeLater,卻不能從事件派發線程中調用invokeAndWait,從事件派發線程調用invokeAndWait的問題是:invokeAndWait鎖定調用它的線程,直到可運行對象從事件派發線程中派發出去并且該可運行的對象的run方法激活,如果從事件派發線程調用invoikeAndWait,則會發生死鎖的狀況,因為invokeAndWait正在等待事件派發,但是,由于是從事件派發線程中調用invokeAndWait,所以直到invokeAndWait返回后事件才能派發。
       ex)actionPerformed();返回的時候事件派發線程才能派發線程,而在actionPerformed中使用invokeAndWait則會導致actionPerformed不能返回。所以也就無法派發invokeAndWait中的線程。

    由于Swing是線程不安全的,所以,從事件派發線程之外的線程訪問Swing組件是不安全的,SwingUtilities類提供這兩種方法用于執行事件派發線程中的代碼

    主站蜘蛛池模板: 亚洲一区无码中文字幕| 亚洲国产精品久久久久婷婷软件| 一区二区三区AV高清免费波多| 亚洲精品乱码久久久久久不卡| 精品国产污污免费网站入口在线| 久久国产亚洲电影天堂| 999久久久免费精品国产| 色五月五月丁香亚洲综合网| 亚洲午夜国产精品无码| 日本视频一区在线观看免费| 高h视频在线免费观看| 亚洲AV成人无码久久精品老人| 久久国内免费视频| 一区二区三区免费视频播放器| 亚洲激情中文字幕| 日本不卡高清中文字幕免费| 韩国免费a级作爱片无码| 亚洲人成人77777网站不卡| 亚洲av无码成人精品区| 欧洲一级毛片免费| 国产乱妇高清无乱码免费| 亚洲人成在线免费观看| 亚洲精品午夜国产VA久久成人| 永久免费毛片在线播放| 中文字幕免费视频精品一| 亚洲日韩精品国产3区| 久久噜噜噜久久亚洲va久| 免费a级毛片在线观看| 狼群影院在线观看免费观看直播| 国产亚洲精品仙踪林在线播放| 亚洲理论片中文字幕电影| 久久精品亚洲男人的天堂| 成人黄页网站免费观看大全| 日韩视频在线观看免费| 一级毛片试看60分钟免费播放| 亚洲AV无码一区二区三区人 | 51午夜精品免费视频| 亚洲色大情网站www| 亚洲一区二区三区在线| 国产成人亚洲精品蜜芽影院| 久久精品国产亚洲AV无码娇色|