`
snoopy7713
  • 浏览: 1161116 次
  • 性别: Icon_minigender_2
  • 来自: 火星郊区
博客专栏
Group-logo
OSGi
浏览量:0
社区版块
存档分类
最新评论

SWT对话框系列:倒计时关闭对话框

    博客分类:
  • SWT
swt 
阅读更多

是不是觉得Windows的倒计时关机对话框很酷?

  

  其实你也可以通过SWT的对话框来实现这个功能,如果你真的够无聊的话,可以用来吓唬一下你的用户,当然你的确定你的人缘很好才行.

   好了,开场白到此为止,下面进入正题:

<!--endfragment-->    我设计这个倒计时对话框主要是为了让我们系统在自动更新完成后自动重启,我们的系统提供了自动更新的功能,而且有个数据传输模块,数据传输模块是使用Wrapper这个工具封装Java程序成服务,数据传输模块会共享RCP客户端的插件Jar包,由于Eclipse插件的特殊性,自动更新完成后可能会在安装目录中存在同名称但不同版本号的插件,具体细节省去7443个字节。

   想实现倒计时对话框,我们可以使用Timer这个定时工具类,这主要考虑到倒计时对话框要和RCP项目的主线程区分开来,对话框弹出不能够影响用户的操作,至少得让他们的有时间保存信息不至于丢失,我们把这个类命名为 TimerMessageDialog .java, 根据MessageDialog中提供的方法,我们无法动态显示提示信息,比如还剩下多少时间.你可以重载MessageDialog的 createMessageArea(Composite composite) 方法,可以再TimerMessageDialog中新增一个字段引用 messageLabel ,比如 localMessageLabel ,然后对 localMessageLabel 的值进行修改,下面是我的实现,可以参考一下:

 

 

  因为我是在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(
true false )
              .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, 
1000 1000 );
      }
      
      
protected   void  buttonPressed( int  buttonId) {
        
if (buttonId  ==  Window.OK) {
          timer.cancel();
          firePropertyChange(IPropery.RESTART_OK_PRESSED, 
false true );
        } 
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);
        }
      }
    
    }
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(
true false )
          .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, 
1000 1000 );
  }

 

   这里的Timer是每一秒钟执行一次,在定时器执行完成后应该让对话框自动关闭,然后可以通知事件发起人来执行对应的操作,从这样设计的角度上看,我们的需要在用户点击确认或者取消或者关闭对话框时响应用户的操作,这样我们的重载父类的 buttonPressed(int buttonId) 方法,在这个方法中执行对应的操作.比如这样:

 

protected   void  buttonPressed( int  buttonId) {
    
if (buttonId  ==  Window.OK) {
      timer.cancel();
      firePropertyChange(IPropery.RESTART_OK_PRESSED, 
false true );
    } 
else   if (buttonId  ==  Window.CANCEL) {
      close();
    }
  }
<!--endfragment--><!--endfragment-->
<!--endfragment--><!--endfragment-->

   这里我使用了java.util包中的 PropertyChangeListener 来监听属性值的修改。这里的对话框应该算是事件源,由这个发起属性事件的修改通知,其他监听类根据接收到的信息作出相应的响应。我在TimerMessageDialog实现了一个内部类: PropertyChangeSupportImpl ,这个类管理通知的对象:  
  <!--endfragment-->

/**
   * 属性修改支持实现类  。 
   * 
@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();
        }
      }
    });
分享到:
评论

相关推荐

    Swt的API使用说明

    Swt提供`FileDialog`类用于打开、保存和选择目录的对话框,方便用户与本地文件系统交互。 **8. 数据绑定** Swt JFace库扩展了Swt,提供了数据绑定功能,使得模型和视图之间的数据同步变得更加简单。 **9. 打印...

    智能时代的生产力变革:AIGC产业应用实践.pdf

    人工智能、大语言模型相关学习资料

    (源码)基于WebAssembly Micro Runtime的嵌入式应用框架.zip

    # 基于WebAssembly Micro Runtime的嵌入式应用框架 ## 项目简介 本项目基于WebAssembly Micro Runtime (WAMR),提供了一个轻量级的WebAssembly运行时环境,适用于嵌入式设备和物联网(IoT)应用。WAMR支持WebAssembly解释器、提前编译(AoT)和即时编译(JIT),并提供了丰富的应用框架和API,支持多种平台和架构。 ## 项目的主要特性和功能 iwasm VM核心 100符合W3C WebAssembly MVP标准。 小巧的运行时二进制大小(解释器85K,AoT 50K)和低内存占用。 通过AoT实现接近原生速度的执行效率。 自实现的模块加载器支持跨Linux、SGX和MCU系统运行。 支持内置libc子集或WASI标准libc。 可嵌入的C API支持。 支持将原生API导出到WebAssembly应用。 应用框架

    芋道 yudao ruoyi-vue-pro crm sql , 更新时间 2024-09-30 ,可对应yudao版本2.4.1

    芋道 yudao ruoyi-vue-pro crm sql , 更新时间 2024-09-30 ,可对应yudao版本2.4.1

    微教育多校版小程序源码 开源版V3.12.75 大数据+营销插件+前端.zip

    微教育多校版小程序源码 开源版V3.12.75 大数据+营销插件+前端 版本号:3.12.75 – 全能版 修复部分用户统计图表不显示的问题 版本号:3.12.74 – 全能版 调整校园首页培训模式下 课程签到柱形图只统计线下课

    AIGC大时代,光模块产业迎风启航-浙商证券-2023.4.14-41页.pdf

    人工智能、大语言模型相关学习资料

    移动端项目-基于Android的随手记APP代码

    移动端项目-基于Android的随手记APP代码

    这是一个pytorch repository的YOLOv4细心的YOLOv4和mobilenet YOLOv4与PAS.zip

    python、yolo、pytorch

    代码目录,traceId 关联,日志,网关

    代码目录,traceId 关联,日志,网关

    systemd-devel-219-78.el7-9.9.x64-86.rpm.tar.gz

    1、文件内容:systemd-devel-219-78.el7_9.9.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/systemd-devel-219-78.el7_9.9.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊

    OpenCV车牌识别.zip

    车牌识别项目

    YOLOv9 YOLOv7 YOLOv7的MIT许可证.zip

    python、yolo、pytorch

    java-springboot+vue厨艺交流平台的设计与实现源码(项目源码-说明文档).zip

    系统选用B/S模式,后端应用springboot框架,前端应用vue框架, MySQL为后台数据库。 本系统基于java设计的各项功能,数据库服务器端采用了Mysql作为后台数据库,使Web与数据库紧密联系起来。 在设计过程中,充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。

    PyTorch张量与自动微分实战指南:从基础到高级

    内容概要:本文详细介绍了PyTorch的张量和自动微分两大核心技术。首先,全面概述了PyTorch的特点及其在深度学习领域的优势,并讲解了PyTorch的安装和配置方法。接着,针对张量这一核心数据结构,阐述了张量的创建方式、常用的操作以及重要属性。再深入到自动微分子系统,解释了自动微分的概念及其工作机制,展示了如何利用计算图和反向传播算法来简化梯度计算。进一步地,在实战案例中演示了构建线性回归模型的全过程,从数据准备、模型定义、损失函数的选择直到训练模型。最后,介绍了一些高级进阶技巧,例如张量广播、拼接、切片和高阶导数的计算,为用户处理复杂任务提供了宝贵经验。 适合人群:有一定编程基础并希望深入理解和运用PyTorch进行深度学习项目的开发者、研究人员以及学生。 使用场景及目标:① 学习并掌握PyTorch框架,尤其是张量和自动微分模块的基础知识;② 结合具体示例理解和实施线性回归模型;③ 提升处理复杂深度学习任务的能力,比如通过高级张量操作优化性能、提高效率。 其他说明:本文不仅涵盖了理论知识还提供了大量的实践范例,能够帮助读者更快地上手和应用所学内容,适用于新手入门到中级水平用户的

    安徽19种土壤类型空间分布-mxd可编辑文件+标准shape文件+标准成图TIF

    本资源为安徽省土壤类型空间分布数据(共19类)。 编图所采用的制图单元有土类、亚类、土属、土种等,对照联合国粮农组织(FAO)土壤分类体系。 数据类型为标准shape格式。 可通过查阅“土壤分类体系”excel文件中的“土壤分类编码表”区分土壤类型。 属性表中的“SOIL_ID”与编码表中的“亚类”是一一对应的。 资源中还包含可编辑mxd文件,方便用户任意操作,同时包含标准TIF格式图片,可直接使用,还包含显示样式修改示意图,可自由选择自己喜欢的配色方案。

    嘉立创EDA专业版安装包

    开发工具,可方便画原理图时,下载原理图及PCB 封装库

    YOLO v3 物体检测算法.zip

    python、yolo、pytorch

    p-07导入CSV文件.py

    p-07导入CSV文件.py

    (源码)基于Arduino的RFID门禁系统.zip

    # 基于Arduino的RFID门禁系统 ## 项目简介 本项目是一个基于Arduino的全面RFID门禁系统,旨在实现安全的访问控制。系统使用MFRC522 RFID读取模块、用于控制门锁机制的伺服电机,以及LED和蜂鸣器为用户提供反馈,确保可靠且便捷的访问管理。 ## 项目的主要特性和功能 1. RFID认证系统读取RFID卡的唯一标识符(UID),并与预定义的授权ID列表进行验证。 2. 伺服电机控制伺服电机控制门的物理锁定机制,根据访问授权进行锁定或解锁操作。 3. 视觉和听觉反馈LED和蜂鸣器提供清晰的视觉和听觉指示,表明访问状态,提升用户体验。 4. 模块化和可定制性代码和硬件设置易于修改或扩展,可添加如键盘或生物识别传感器等额外功能。 ## 安装使用步骤 ### 步骤1收集组件 Arduino开发板(如Arduino Uno) MFRC522 RFID读取模块 伺服电机 LED和电阻 无源蜂鸣器 跳线

Global site tag (gtag.js) - Google Analytics