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

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

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

    好好生活,努力工作,天天向上!

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      46 Posts :: 1 Stories :: 178 Comments :: 0 Trackbacks

      是不是覺得Windows的倒計時關機對話框很酷?
                           

       其實你也可以通過SWT的對話框來實現這個功能,如果你真的夠無聊的話,可以用來嚇唬一下你的用戶,當然你的確定你的人緣很好才行.

       好了,開場白到此為止,下面進入正題:

        我設計這個倒計時對話框主要是為了讓我們系統在自動更新完成后自動重啟,我們的系統提供了自動更新的功能,而且有個數據傳輸模塊,數據傳輸模塊是使用Wrapper這個工具封裝Java程序成服務,數據傳輸模塊會共享RCP客戶端的插件Jar包,由于Eclipse插件的特殊性,自動更新完成后可能會在安裝目錄中存在同名稱但不同版本號的插件,具體細節省去7443個字節。

       想實現倒計時對話框,我們可以使用Timer這個定時工具類,這主要考慮到倒計時對話框要和RCP項目的主線程區分開來,對話框彈出不能夠影響用戶的操作,至少得讓他們的有時間保存信息不至于丟失,我們把這個類命名為 TimerMessageDialog .java, 根據MessageDialog中提供的方法,我們無法動態顯示提示信息,比如還剩下多少時間.你可以重載MessageDialog的 createMessageArea(Composite composite) 方法,可以再TimerMessageDialog中新增一個字段引用 messageLabel ,比如 localMessageLabel ,然后對 localMessageLabel 的值進行修改,下面是我的實現,可以參考一下:

     
    protected Control createMessageArea(Composite composite) {
        
    // create composite
        
    // create image
        Image image = getImage();
        
    if (image != null) {
          imageLabel 
    = new Label(composite, SWT.NULL);
          image.setBackground(imageLabel.getBackground());
          imageLabel.setImage(image);
    //      addAccessibleListeners(imageLabel, image);
          GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING)
              .applyTo(imageLabel);
        }
        
    // create message
        if (message != null) {
          messageLabel 
    = new Label(composite, getMessageLabelStyle());
          TimerMessageDialog.localMessageLabel 
    = messageLabel;
          messageLabel.setText(message);
          GridDataFactory
              .fillDefaults()
              .align(SWT.FILL, SWT.BEGINNING)
              .grab(
    truefalse)
              .hint(
                  convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH),
                  SWT.DEFAULT).applyTo(messageLabel);
        }
        
    return composite;
      }

       然后我們添加一個打開對話框的方法:  open(final int second,final String message) ,second表示倒計時時間,message表示提示信息,在open方法中新建一個 Timer 對象。對了,為了讓MessageDialog彈出后不阻塞線程的執行,需要在調用對話框的open方法之前調用 setBlockOnOpen(false); 方法,下面是我的實現,大家可以參考一下:

    /**
       * 打開定時關閉對話框,顧名思義,就是在指定的時間自動關閉  。
       * 
    @author 劉堯興
       * 
    @param second
       * 
    @param message 
       
    */
      
    public void open(final int second,final String message) {
        setBlockOnOpen(
    false);
        open();
        
    //    final MessageFormat format = new MessageFormat("系統檢查到重要插件的更新,系統將會在 {0} 秒后自動重啟,請注意保存文件");
        
        timer 
    = new Timer("檢查更新");
        
    final TimerTask task = new TimerTask() {
          
    int count = second;
          
    public void run() {
            Display display 
    = Display.getDefault();
            
    if (display == null) {
              
    return;
            }
            display.asyncExec(
    new Runnable() {
              
    public void run() {
                
    try {

                  
    if (count == 0) {
                    cancel();
                    buttonPressed(Window.OK);
                  } 
    else {
                    count 
    -= 1;
                    
    if (!localMessageLabel.isDisposed()&&localMessageLabel != null) {
                      localMessageLabel.setText(message
    +"系統將在:" + count + "秒后自動重啟");
    //                localMessageLabel.setText(format.format(new Object[]{new Integer(count)}));
                    }
                  }
                
                }
    catch (Exception e) {
                  e.printStackTrace();
                }
              }
            });
          }
        };
        timer.schedule(task, 
    10001000);
      }

       這里的Timer是每一秒鐘執行一次,在定時器執行完成后應該讓對話框自動關閉,然后可以通知事件發起人來執行對應的操作,從這樣設計的角度上看,我們的需要在用戶點擊確認或者取消或者關閉對話框時響應用戶的操作,這樣我們的重載父類的 buttonPressed(int buttonId) 方法,在這個方法中執行對應的操作.比如這樣:

     
    protected void buttonPressed(int buttonId) {
        
    if(buttonId == Window.OK) {
          timer.cancel();
          firePropertyChange(IPropery.RESTART_OK_PRESSED, 
    falsetrue);
        } 
    else if(buttonId == Window.CANCEL) {
          close();
        }
      }

       這里我使用了java.util包中的 PropertyChangeListener 來監聽屬性值的修改。這里的對話框應該算是事件源,由這個發起屬性事件的修改通知,其他監聽類根據接收到的信息作出相應的響應。我在TimerMessageDialog實現了一個內部類: PropertyChangeSupportImpl ,這個類管理通知的對象: 
     

    /**
       * 屬性修改支持實現類  。 
       * 
    @author 劉堯興
       * <p>2009-8-18</p>
       
    */
      
    public class PropertyChangeSupportImpl {
        
        
    /** 屬性修改支持     */
        PropertyChangeSupport listeners 
    = new PropertyChangeSupport(this);

        
    /**
         * 添加屬性修改事件  。
         * 
    @author 劉堯興
         * 
    @param l
         
    */
        
    public void addPropertyChangeListener(PropertyChangeListener l) {
          listeners.addPropertyChangeListener(l);
        }

        
    /**
         * 通知修改事件發生  。
         * 
    @author 劉堯興
         * 
    @param prop
         * 
    @param old
         * 
    @param newValue
         
    */
        
    public void firePropertyChange(String prop, Object old, Object newValue) {
          listeners.firePropertyChange(prop, old, newValue);
        }

        
    /**
         * 通知事件修改  。
         * 
    @author 劉堯興
         * 
    @param prop
         * 
    @param child
         
    */
        
    protected void fireStructureChange(String prop, Object child) {
          listeners.firePropertyChange(prop, 
    null, child);
        }

        
    /**
         * 刪除屬性修改事件  。
         * 
    @author 劉堯興
         * 
    @param l
         
    */
        
    public void removePropertyChangeListener(PropertyChangeListener l) {
          listeners.removePropertyChangeListener(l);
        }
      }

       在完成這些之后,在監聽類中注冊一個屬性修改的事件,比如在UpdatePlan這個類中執行TimerMessageDialog的打開操作,那就的讓UpdatePlan這個類實現 PropertyChangeListener 這個接口并實現 propertyChange(final PropertyChangeEvent evt) 這個方法,這個方法可以根據傳過來的屬性名稱和屬性值執行相應的操作。UpdatePlan屬性注冊方式是:

    Display.getDefault().asyncExec(new Runnable() {
          @Override
          
    public void run() {
            
    try {
              TimerMessageDialog dialog 
    = new TimerMessageDialog(Display.getDefault().getActiveShell(),"系統信息","系統將要自動重啟");
              dialog.addPropertyChangeListener(
    this);
              dialog.open(
    30,"");
            }
            
    catch (Exception e) {
              e.printStackTrace();
            }
          }
        });
      因為我是在RCP的非UI現在調用這個對話框,所以需要在Display的asyncExec方法啟用一個新的異步線程.這樣就不會拋出非法的線程訪問異常了。

      看下效果:
       
      
      下面是完整的類
     
        package com.cnex.oss.managerupdate.tools;
        
        
    import java.beans.PropertyChangeListener;
        
    import java.beans.PropertyChangeSupport;
        
    import java.util.Timer;
        
    import java.util.TimerTask;
        
        
    import org.eclipse.jface.dialogs.IDialogConstants;
        
    import org.eclipse.jface.layout.GridDataFactory;
        
    import org.eclipse.jface.window.Window;
        
    import org.eclipse.swt.SWT;
        
    import org.eclipse.swt.graphics.Image;
        
    import org.eclipse.swt.widgets.Composite;
        
    import org.eclipse.swt.widgets.Control;
        
    import org.eclipse.swt.widgets.Display;
        
    import org.eclipse.swt.widgets.Label;
        
    import org.eclipse.swt.widgets.Shell;
        
        
    /**
         * 定時執行對話框 。 
         * 
    @author 劉堯興
         * <p>2009-12-7</p>
         
    */
        
    public class TimerMessageDialog extends MessageDialog2 {
        
          
    /** 標簽文本     */
          
    protected static Label localMessageLabel;
          
          
    /** 屬性修改支持實現類     */
          
    private PropertyChangeSupportImpl instance = new PropertyChangeSupportImpl();
        
          
    /** 定時器     */
          
    private Timer timer;
          
          
    /**
           * 構造函數。
           * 
    @param parentShell
           * 
    @param dialogTitle
           * 
    @param dialogMessage
           
    */
          
    public TimerMessageDialog(Shell parentShell, String dialogTitle, String dialogMessage) {
            
    super(parentShell, dialogTitle, null, dialogMessage, INFORMATION, new String[] {"立即重啟","隱藏"}, 0);
            setShellStyle(SWT.BORDER 
    | SWT.MIN);
          }
        
          
    protected Control createMessageArea(Composite composite) {
            
    // create composite
            
    // create image
            Image image = getImage();
            
    if (image != null) {
              imageLabel 
    = new Label(composite, SWT.NULL);
              image.setBackground(imageLabel.getBackground());
              imageLabel.setImage(image);
        
    //      addAccessibleListeners(imageLabel, image);
              GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING)
                  .applyTo(imageLabel);
            }
            
    // create message
            if (message != null) {
              messageLabel 
    = new Label(composite, getMessageLabelStyle());
              TimerMessageDialog.localMessageLabel 
    = messageLabel;
              messageLabel.setText(message);
              GridDataFactory
                  .fillDefaults()
                  .align(SWT.FILL, SWT.BEGINNING)
                  .grab(
    truefalse)
                  .hint(
                      convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH),
                      SWT.DEFAULT).applyTo(messageLabel);
            }
            
    return composite;
          }
          
          
    /**
           * 打開定時關閉對話框,顧名思義,就是在指定的時間自動關閉  。
           * 
    @author 劉堯興
           * 
    @param second
           * 
    @param message 
           
    */
          
    public void open(final int second,final String message) {
            setBlockOnOpen(
    false);
            open();
            
        
    //    final MessageFormat format = new MessageFormat("系統檢查到重要插件的更新,系統將會在 {0} 秒后自動重啟,請注意保存文件");
            
            timer 
    = new Timer("檢查更新");
            
    final TimerTask task = new TimerTask() {
              
    int count = second;
              
    public void run() {
                Display display 
    = Display.getDefault();
                
    if (display == null) {
                  
    return;
                }
                display.asyncExec(
    new Runnable() {
                  
    public void run() {
                    
    try {
        
                      
    if (count == 0) {
                        cancel();
                        buttonPressed(Window.OK);
                      } 
    else {
                        count 
    -= 1;
                        
    if (!localMessageLabel.isDisposed()&&localMessageLabel != null) {
                          localMessageLabel.setText(message
    +"系統將在:" + count + "秒后自動重啟");
        
    //                localMessageLabel.setText(format.format(new Object[]{new Integer(count)}));
                        }
                      }
                    
                    }
    catch (Exception e) {
                      e.printStackTrace();
                    }
                  }
                });
              }
            };
            timer.schedule(task, 
    10001000);
          }
          
          
    protected void buttonPressed(int buttonId) {
            
    if(buttonId == Window.OK) {
              timer.cancel();
              firePropertyChange(IPropery.RESTART_OK_PRESSED, 
    falsetrue);
            } 
    else if(buttonId == Window.CANCEL) {
              close();
            }
          }
          
          
    /**
           * 添加屬性事件  。
           * 
    @author 劉堯興
           * 
    @param l
           
    */
          
    public void addPropertyChangeListener(PropertyChangeListener l) {
            instance.addPropertyChangeListener(l);
          }
          
          
    /**
           * 刪除屬性修改事件  。
           * 
    @author 劉堯興
           * 
    @param l
           
    */
          
    public void removePropertyChangeListener(PropertyChangeListener l) {
            instance.removePropertyChangeListener(l);
          }
          
          
    /**
           * 通知屬性修改事件(通知前臺代碼修改)  。
           * 
    @author 劉堯興
           * 
    @param prop
           * 
    @param old
           * 
    @param newValue
           
    */
          
    public void firePropertyChange(String prop, Object old, Object newValue) {
            instance.firePropertyChange(prop, old, newValue);
          }
          
          
    /**
           * 屬性修改支持實現類  。 
           * 
    @author 劉堯興
           * <p>2009-8-18</p>
           
    */
          
    public class PropertyChangeSupportImpl {
            
            
    /** 屬性修改支持     */
            PropertyChangeSupport listeners 
    = new PropertyChangeSupport(this);
        
            
    /**
             * 添加屬性修改事件  。
             * 
    @author 劉堯興
             * 
    @param l
             
    */
            
    public void addPropertyChangeListener(PropertyChangeListener l) {
              listeners.addPropertyChangeListener(l);
            }
        
            
    /**
             * 通知修改事件發生  。
             * 
    @author 劉堯興
             * 
    @param prop
             * 
    @param old
             * 
    @param newValue
             
    */
            
    public void firePropertyChange(String prop, Object old, Object newValue) {
              listeners.firePropertyChange(prop, old, newValue);
            }
        
            
    /**
             * 通知事件修改  。
             * 
    @author 劉堯興
             * 
    @param prop
             * 
    @param child
             
    */
            
    protected void fireStructureChange(String prop, Object child) {
              listeners.firePropertyChange(prop, 
    null, child);
            }
        
            
    /**
             * 刪除屬性修改事件  。
             * 
    @author 劉堯興
             * 
    @param l
             
    */
            
    public void removePropertyChangeListener(PropertyChangeListener l) {
              listeners.removePropertyChangeListener(l);
            }
          }
        
        }
    posted on 2009-12-09 08:32 VWPOLO 閱讀(2409) 評論(4)  編輯  收藏

    Feedback

    # re: SWT對話框系列:倒計時關閉對話框.doc 2009-12-09 10:24 20G高壓鍋爐管
    說的挺好  回復  更多評論
      

    # re: SWT對話框系列:倒計時關閉對話框.doc 2009-12-09 11:48 feenn
    中間在說PropertyChangeListener的時候說錯了吧,PropertyChangeListener是java.beans中的接口,代碼中都寫正確了的  回復  更多評論
      

    # re: SWT對話框系列:倒計時關閉對話框.doc 2009-12-10 10:45 夢芭莎內衣
    的大方廣闊的風格  回復  更多評論
      

    # re: SWT對話框系列:倒計時關閉對話框.doc 2009-12-11 16:20 av
    很好的小功能,收藏了!  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 91成人免费观看在线观看| 中文字幕乱码亚洲精品一区| 亚洲AV无码一区二区三区牲色 | 国产成人免费高清激情明星| 亚洲免费观看在线视频| 久久亚洲精品国产精品黑人| 日韩a级无码免费视频| 黑人精品videos亚洲人| 中文字幕无码精品亚洲资源网久久| www.999精品视频观看免费| 亚洲国产精品综合久久网络| 麻豆安全免费网址入口| 亚洲中文字幕伊人久久无码| 亚洲一区二区三区免费观看| 一区二区三区在线观看免费| 亚洲一区二区三区自拍公司| 国产精品亚洲综合一区在线观看| 国产精品免费一级在线观看| 污污免费在线观看| 亚洲va久久久噜噜噜久久天堂 | 亚洲av日韩av永久在线观看| 国产极品美女高潮抽搐免费网站| 无码精品人妻一区二区三区免费| 91久久成人免费| 亚洲国产欧美国产综合一区 | 免费一级毛片不卡不收费| 亚洲成人黄色在线| 蜜臀91精品国产免费观看| 老外毛片免费视频播放| 亚洲精品国产精品乱码不卡√| 久久精品国产免费观看三人同眠| 亚洲第一第二第三第四第五第六| 久久精品国产精品亚洲人人| 亚洲免费在线视频| 亚洲av成人无码网站…| 亚洲av无码片在线播放| 夜夜爽免费888视频| 亚洲首页国产精品丝袜| 久久久久国产精品免费网站| 亚洲最大无码中文字幕| 亚洲午夜无码久久久久|