是不是觉得Windows的倒计时关机对话框很酷?
其实你也可以通过SWT的对话框来实现这个功能,如果你真的够无聊的话,可以用来吓唬一下你的用户,当然你的确定你的人缘很好才行.
好了,开场白到此为止,下面进入正题:
<!--endfragment--> 我设计这个倒计时对话框主要是为了让我们系统在自动更新完成后自动重启,我们的系统提供了自动更新的功能,而且有个数据传输模块,数据传输模块是使用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(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();
}
}
});
因为我是在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);
}
}
}
分享到:
相关推荐
SWT(Standard Widget Toolkit)是Java编程中用于创建图形用户界面(GUI)的一种库,它为开发者提供了丰富的控件和对话框。在SWT中,`MessageBox`是一个用于显示简单的消息对话框的类,通常用来向用户显示警告、确认...
对于“java的swing实现计时与倒计时”这一主题,我们将探讨如何利用Swing构建一个能够输入起始时间和终止时间,并且可以执行计时和倒计时功能的应用程序。 首先,Swing中的JFrame是应用程序的主要窗口,它包含其他...
SWT(Standard Widget Toolkit)是Java编程中用于创建桌面应用程序的一种图形用户界面(GUI)工具包,由Eclipse基金会维护。它提供了丰富的组件和API,让开发者能够构建功能强大的跨平台应用。本教程主要讲解如何在...
【标题】"org.eclipse.swt相关所有jar包"涵盖了用于JAVA应用程序与浏览器集成的关键库 【描述】中的"org.eclipse.swt"是指Eclipse Standard/Widgets工具包,这是一个开源的Java库,允许开发人员在多种平台上创建...
JFace 的核心价值在于它提供了一系列的工具类和控件,这些工具类和控件可以帮助开发者快速构建常见的 UI 元素,如对话框、表格、树形结构等,大大减少了代码量和开发时间。 #### 创建JFace应用的基本步骤 1. **...
此 repo 包含用于 Python 3 的 libccv 的 SWT 算法的包装器。它与 Linux、macOS 和 Docker 兼容。 有关更多信息,请参阅我的博文:http: 用法 from swt_python3 import swt buffer = open ( "input.jpg" , "rb" )...
org.eclipse.swt.SWT.class org.eclipse.swt.SWTError.class org.eclipse.swt.SWTException.class org.eclipse.swt.accessibility.ACC.class org.eclipse.swt.accessibility.Accessible.class org.eclipse.swt....
JFace的Dialog类可能被用来创建登录对话框的基本结构,包括标题、边框、关闭按钮等。开发者可能还使用了Text组件来接收用户名和密码输入,Button组件用于提交或取消操作。通过组合这些基本组件,可以构建出具有完整...
5. **对话框**:展示如何创建和使用各种对话框,如消息对话框(MessageDialog)、文件选择对话框(FileDialog)等。 6. **复合组件**:介绍如何组合多个SWT组件创建自定义的复合组件。 7. **SWT与JFace**:JFace是...
主要讲述了Jface向导式对话框的编写及代码。能够正确的运行在Eclipse中,希望能帮有所帮助
根据提供的文件信息,可以看出本文主要讨论的是如何在 SWT (Standard Widget Toolkit) 的 Table 控件中实现文本换行的功能。SWT 是一个用于开发基于 Java 的桌面应用程序的工具包,它提供了丰富的用户界面组件来帮助...
org.eclipse.swt 相关jar包,JAVA调用火狐内核制作浏览器教程中所需,供各位下载,可在我的博客中查看详细用法。
SWT examples,SWT官方例子:http://www.eclipse.org/swt/examples.php 该页面所要下载的例子 其中,swt的例子在\plugins\org.eclipse.swt.examples.source_3.7.0.v3740f.jar中
SWT包括各种基本的UI元素,如按钮、文本框、列表、树视图等,以及高级组件如表单、进度条和对话框。它的核心优势在于提供了跨平台的原生界面支持,避免了Java AWT和Swing中常见的“Java Look and Feel”。 2. JFace...
### 在SWT开发中实现的日历对话框 #### 概述 SWT(Standard Widget Toolkit)是Eclipse平台上的一种用于创建图形用户界面的工具包。它提供了丰富的组件库,允许开发者构建高性能、外观本地化的应用程序。本文将...
SWT库包括一系列基本组件,如按钮、文本框、列表视图等,以及更复杂的元素,如树视图、表格和对话框。 2. SWT与JFace的关系: JFace是建立在SWT之上的抽象层,它简化了SWT的使用,通过提供更多的高级API和模型视图...
JFace是建立在SWT之上的抽象层,它简化了GUI开发,提供了数据绑定、视图模型、对话框等功能。JFace的目的是使代码更简洁,减少重复工作,提升可读性和可维护性。在本教程中,JFace与SWT一起被提及,意味着我们不仅会...
【标题】"swt-alerts:Chrome火车状态扩展"是一个基于JavaScript开发的Chrome浏览器扩展程序,主要用于提供火车运行状态的实时警报服务。这个扩展利用了Chrome浏览器的扩展框架,将用户界面与JavaScript编程语言相...
4. **对话框**:SWT提供了诸如消息对话框(MessageDialog)、输入对话框(InputDialog)和文件选择对话框(FileDialog)等,学习如何创建和使用这些对话框,可以增强应用的交互性。 5. **拖放操作**:SWT支持拖放...
android-swt-演示演示如何使用桌面 Java 和 SWT 显示 Android 自定义绘制视图的原型这个原型包括两个项目: DrawIt - 一个非常简单的 Android 应用程序,其中包含一个自定义绘制的视图 (TestView) AndroidPaint - 一...