关于JFace中的进度条对话框(ProgressMonitorDialog类)

时间:2022-08-24 14:17:51

在Windows操作系统中,最常用的进度条对话框就是文件复制时的弹出框,如果想让用户愉快的使用你开发

的软件,那么在执行某个较长时间的操作时候,就应该弹出一个进度条提示框,告诉用户程序正在做什么.

做到什么地步了.进度条提示框可以让用户更有安全感也可以提高用户的耐心.

前面用到的SWT组件的进度条ProgressBar类太底层,还需要处理诸如线程分配的问题.现在

JFace提供了更容易使用的ProgressMonitorDialog类来创建进度条对话框.

标准的进度条对话框:

ProgressMonitorDialog类还算简单,只要将执行代码用IRunnableWithProgress类包装一下即可,本实例中在窗口中建立 一个GO按钮,当单击该按钮时执行一个需时较长的操作(以每次循环停顿一秒来模拟),并弹出一个进度条对话框.程序在未加进度条时的代码如下:

ProgressMonitorDialog.java

 import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell; public class ProgressMonitorDialog1 { public static void main(String[] args) {
new ProgressMonitorDialog1().open();
} public void open() {
final Display display = Display.getDefault();
final Shell shell = new Shell();
shell.setSize(500, 375); shell.setLayout(new RowLayout());
Button button = new Button(shell, SWT.NONE);
button.setText(" GO ");
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
// 创建进度条对话框的处理过程对象
IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
monitor.beginTask("开始执行......", 10);
for (int i = 0; i < 10; i++) {// 循环10次,每次间隔一秒
if (monitor.isCanceled()) // 随时监控是否选择了对话框的“取消”按钮
return;// 中断处理
try {
Thread.sleep(1000);
} catch (Throwable t) {}
monitor.setTaskName("第" + (i + 1) + "次循环");// 提示信息
monitor.worked(1);// 进度条前进一步
}
monitor.done();// 进度条前进到完成
}
};
try {
// 创建一个进度条对话框,并将runnable传入
// 第一个参数推荐设为true,如果设为false则处理程序会运行在UI线程里,界面将有一点停滞感。
// 第二个参数:true=对话框的“取消”按钮有效
new ProgressMonitorDialog(shell).run(true, true, runnable);
} catch (Exception e2) {
e2.printStackTrace();
}
}
}); shell.layout();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
} }

运行结果:

关于JFace中的进度条对话框(ProgressMonitorDialog类)

要在执行程序时候弹出一个进度条,则就要对GO按钮的widgetSelected方法做修改(上面代码已经修改完毕):

· 编写一个处理过程接口IRunnableWithProgress的匿名实现类,并将耗时代码嵌入其run方法中,可以用run方法的参数monitor操作进度条向前移动.当然这个类写成命名内部类或者外部类也是可以的.

·创建一个ProgressMonitorDialog对话框对象,并用它的run方法弹出进度条对话框.接收IRunnableWithProgress对象做参数.run方法有受控异常需要处理,需要用try/catch括起来.

程序说明:如果无法确定进度条需要多少格长度,可以将值设置的大一些,即使真实循环数没有达到或者超过了也不会引起程序出错.

进度条对话框的实现代码看是复杂,其实简化而无变化,代码框架都一个样,关键是把IRunnableWithProgress.run方法中的处理程序写好.

反复显示的进度条对话框.

有些后台任务,可能无法将它分解成多少部,它就是一个单一的长时间的处理过程.这时可以弹出一个对话框,进度条不断的重复移动,直到后台任务结束,或被中止.

实际上这种方案后台处理程序和前台弹出进度框被分为了两个独立的部分,但它们之间仍然需要一个信使来传递信息.比如,后台任务完成了,那么就应该通知前台进度框关闭:单击了前台进度框的"取消"按钮,也需要通知后台任务中断处理.这个信使可以用一个boolean变量标志位来充当,不必去通知前台后台,自己监控该变量的变化即可.具体的实体如下代码所示:

ProgressMonitorDialog2.java

 import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell; public class ProgressMonitorDialog2 { public static void main(String[] args) {
new ProgressMonitorDialog2().open();
} public void open() {
final Display display = Display.getDefault();
final Shell shell = new Shell();
shell.setSize(500, 375); shell.setLayout(new RowLayout());
Button button = new Button(shell, SWT.NONE);
button.setText(" GO ");
button.addSelectionListener(new SelectionAdapter() {
private boolean stopFlag;// 停止标志 private void go() {
for (int i = 0; i < 10; i++) {// 循环10次,每次间隔一秒
System.out.println("第" + (i + 1) + "个任务执行完毕");
if (stopFlag) {// 监控是否要让停止后台任务
System.out.println("被中断了");
return;
}
try {
Thread.sleep(1000);
} catch (Throwable t) {}
}
stopFlag = true;// 执行完毕后把标志位设为停止,好通知给进度框
System.out.println("全部任务执行完毕");
} public void widgetSelected(SelectionEvent e) {
stopFlag = false;// 每次都设初值为false
new Thread() {// 把后台任务放到一个新开线程里执行
public void run() {
go();
}
}.start();
showProgressDialog();// 打开一个进度框
} private void showProgressDialog() {
IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
monitor.beginTask("正在执行中......", 30);
int i = 0;
while (true) {
// 监听是否单击了进度框的“取消”按钮,stopFlag则是监听后台任务是否停止
if (monitor.isCanceled() || stopFlag) {
stopFlag = true; // 单击了“取消”按钮要设标志位为停止,好通知后台任务中断执行
break;// 中断处理
}
// i到30后清零。并将进度条重新来过
if ((++i) == 30) {
i = 0;
monitor.beginTask("正在执行中......", 30);
}
// 进度条每前进一步体息一会,不用太长或太短,时间可任意设。
try {
Thread.sleep(99);
} catch (Throwable t) {}
monitor.worked(1);// 进度条前进一步
}
monitor.done();// 进度条前进到完成
}
};
try {
new ProgressMonitorDialog(shell).run(true, true, runnable);
} catch (Exception e) {
e.printStackTrace();
}
}
}); shell.layout();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
} }

运行结果如下:

关于JFace中的进度条对话框(ProgressMonitorDialog类)

点击cancle按钮,对应的后面没有执行的任务取消.

关于JFace中的进度条对话框(ProgressMonitorDialog类)

封装反复显示的进度条对话框

虽然实例2实现了一个不断反复显示的进度框,但它的代码如此凌乱,而且许多代码复生冗长,所以应该把这种不断反复的进度框封装成一个组件,让其使用起来更方便.封装成组件会遇到两个问题:

(1)如何封装?第一个想到的是集成ProgressMonitorDialog来实现新组件.这种方法未尝不可,但这样新组件就和ProgressMonitorDialog类耦合在了一起,如果以后不想用进度条而想改用一个动画,就不容易了.所以还是用组合方式的扩展比较好.实现起来也简单.

(2)封装后分成了多个类.由于boolean是简单类型是值传递.它已经不适合作为进度框和后台任务之间的信使.而Boolean类虽然是引用传递,但它是不可变化类.要改变它要重新创建一个对象.所以他也不能用.因此方案只有两个,用boolean数组,或者创建一个专门的标识类做信使.这里选择第二个方案.

打方案定了,接着开始做具体的实现,首先是这个新组件应该提供什么方法.可以从使用的角度来考虑,经过考虑之后使用方式可以参照ProgressMonitorDialog.具体代码如下所示:

ProgressMonitorDialog3.java

 import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell; public class ProgressMonitorDialog3 { public static void main(String[] args) {
new ProgressMonitorDialog3().open();
} public void open() {
final Display display = Display.getDefault();
final Shell shell = new Shell();
shell.setSize(500, 375); shell.setLayout(new RowLayout());
Button button = new Button(shell, SWT.NONE);
button.setText(" GO ");
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
new LoopProgressDialog(shell).run(true, new IProgressDialogRunnable() {
public void run(BooleanFlag stopFlag) {
for (int i = 0; i < 10; i++) {
System.out.println("第" + (i + 1) + "个任务执行完毕");
if (stopFlag.getFlag()) {
System.out.println("被中断了");
return;
}
try {
Thread.sleep(1000);
} catch (Throwable t) {}
}
stopFlag.setFlag(true);
System.out.println("全部任务执行完毕");
}
});
}
}); shell.layout();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
} }

程序说明:LoopProgressDialog是这里的新组件.它的使用看起来非常像ProgressMonitorDialog,区别是:IProgressDialogRunnable是一个我们自己定义的接口,它提供一个run方法.方法的参数是一个用作信使的标志类BooleanFlag.BooleanFlag实际是对boolean的一个封装,和Boolean封装类不同的是它提供了setFlag修改方法.

IProgressDialogRunnable和BooleanFlag的代码比较简单.如下所示:

IProgressDialogRunnable.java

public interface IProgressDialogRunnable {
void run(BooleanFlag stopFlag);
}

BooleanFlag.java

 public final class BooleanFlag {
private boolean flag = false; public BooleanFlag() {} public BooleanFlag(boolean flag) {
this.flag = flag;
} public synchronized boolean getFlag() {
return flag;
} public synchronized void setFlag(boolean flag) {
this.flag = flag;
}
}

接下来就是新组件LoopProgressDialog的实现了.

LoopProgressDialog.java

 import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Shell; public class LoopProgressDialog {
private ProgressMonitorDialog dialog;
public BooleanFlag stopFlag = new BooleanFlag(); public LoopProgressDialog(Shell shell) {
dialog = new ProgressMonitorDialog(shell);
} public void run(boolean cancelable, final IProgressDialogRunnable runnable) {
new Thread() {
public void run() {
runnable.run(stopFlag);
}
}.start(); try {
dialog.run(true, cancelable, new LoopRunnable());
} catch (Exception e) {
e.printStackTrace();
}
} private class LoopRunnable implements IRunnableWithProgress {
public void run(IProgressMonitor monitor) {
monitor.beginTask("正在执行中......", 30);
int i = 0;
while (true) {
// 监听是否单击了进度框的“取消”按钮,stopFlag则是监听后台任务是否停止
if (monitor.isCanceled() || stopFlag.getFlag()) {
stopFlag.setFlag(true);
break;// 中断处理
}
// i到30后清零。并将进度条重新来过
if ((++i) == 30) {
i = 0;
monitor.beginTask("正在执行中......", 30);
}
// 进度条每前进一步体息一会,不用太长或太短,时间可任意设。
try {
Thread.sleep(99);
} catch (Throwable t) {}
monitor.worked(1);// 进度条前进一步
}
monitor.done();// 进度条前进到完成
}
} }

用动画GIF来表示进度

ProgressMonitorDialog4.java和ProgressMonitorDialog3.java唯一不同之处就是把LoopProgressDialog改成了动画GIF界面类LoopImageDialog.

LoopImageDialog的内部实现没有采用Dialog或者其子类,而是用Shell来弹出界面的.所以严格来说它不能算是一个对话框.

ProgressMonitorDialog4.java

 import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell; public class ProgressMonitorDialog4 { public static void main(String[] args) {
new ProgressMonitorDialog4().open();
} public void open() {
final Display display = Display.getDefault();
final Shell shell = new Shell();
shell.setSize(500, 375); shell.setLayout(new RowLayout());
Button button = new Button(shell, SWT.NONE);
button.setText(" GO ");
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
new LoopImageDialog(shell).run(true, new IProgressDialogRunnable() {
public void run(BooleanFlag stopFlag) {
for (int i = 0; i < 10; i++) {
System.out.println("第" + (i + 1) + "个任务执行完毕");
if (stopFlag.getFlag()) {
System.out.println("被中断了");
return;
}
try {
Thread.sleep(1000);
} catch (Throwable t) {}
}
stopFlag.setFlag(true);
System.out.println("全部任务执行完毕");
}
});
}
}); shell.layout();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
} }

LoopImageDialog.java

 import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell; import cn.com.chengang.swt.SWTUtils; public class LoopImageDialog {
private Shell parentShell;
public BooleanFlag stopFlag = new BooleanFlag(); protected LoopImageDialog(Shell parentShell) {
this.parentShell = parentShell;
} public void run(boolean cancelable, final IProgressDialogRunnable runnable) {
new Thread() {
public void run() {
runnable.run(stopFlag);
}
}.start();
showDialog();
} private void showDialog() {
final Display display = Display.getDefault();
Shell shell = new Shell(parentShell);
shell.setSize(250, 180);
SWTUtils.setCenter(shell); // 使用shell居中
shell.setLayout(new FillLayout());
// 在Shell窗口显示一个动画GIF
final ImageLoader imageLoader = new ImageLoader();
imageLoader.load("icons/animation2.gif");
new AnimationGIF(shell, SWT.BORDER, imageLoader);
// 弹出窗口。Shell和Dialog不同,它在open弹出界面之后会继承执行下面的语句
shell.open();
while (!shell.isDisposed()) {
if (stopFlag.getFlag())
shell.dispose();
if (!display.readAndDispatch())
display.sleep();
}
stopFlag.setFlag(true);
}
}

关于JFace中的进度条对话框(ProgressMonitorDialog类)的更多相关文章

  1. 关于JFace中的向导式对话框&lpar;WizardDialog类&rpar;

    向导式对话框是一种非常友好的界面,它能够引导用户一步步的输入信息.Eclipse的"新建项目",就是这样的向导式对话框. 在Eclipse中向导式对话框的开发是很简单的,它由Wiz ...

  2. android 对话框中的进度条 &lpar;ProgressDialog&rpar;

    from:http://byandby.iteye.com/blog/817214 显然要定义对话框进度条就要用ProgressDialog,首先我们需要创建ProgressDialog对象,当然这里 ...

  3. 【转】24&period; android dialog ——ProgressDialog 进度条对话框详解

    原文网址:http://blog.csdn.net/jamesliulyc/article/details/6375598 首先在onCreateDialog方法里创建一个ProgressDialog ...

  4. ProgressWheelDialogUtil【ProgressWheel Material样式进度条对话框】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 简单封装网络请求时的加载对话框以及上传.下载文件的进度加载对话框. 效果图 代码分析 ProgressWheel : 自定义view ...

  5. Android开发 ---构建对话框Builder对象,消息提示框、列表对话框、单选提示框、多选提示框、日期&sol;时间对话框、进度条对话框、自定义对话框、投影

    效果图: 1.activity_main.xml 描述: a.定义了一个消息提示框按钮 点击按钮弹出消息 b.定义了一个选择城市的输入框 点击按钮选择城市 c.定义了一个单选提示框按钮 点击按钮选择某 ...

  6. 实用ExtJS教程100例-003:进度条对话框Ext&period;MessageBox&period;progress

    在上一篇内容中我们介绍了三种常用的MessageBox提示框,在这篇文章中,我们将演示如何在对话框中使用进度条. 进度条对话框 我们可以使用下面的代码来在MessageBox中显示一个进度条: Ext ...

  7. Android 进度条对话框ProgressDialog

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  8. AlertDialog之常见对话框(单选对话框、多选对话框、进度条对话框)

    单选对话框,顾名思义就是只能选一项(setSingleChoiceItems(Items,)) public void click(View v){ //创建对话框类 AlertDialog.Buil ...

  9. 如何在UIAlertView中显示进度条

    今天这个问题是,在一个iPhone程序中,我要在后台做大量的数据处理,希望在界面上显示一个进度条(Progress Bar)使得用户了解处理进度.这个进度条应该是在一个模态的窗口中,使界 今天这个问题 ...

随机推荐

  1. springmvc 文件上传实现&lpar;不是服务器的&rpar;

    1.spring使用了apache-commons下的上传组件,因此,我们需要引用2个jar包 1)apache-commons-fileupload.jar 2 ) apache-commons-i ...

  2. Syncfusion 复选框 ComboBoxAdv

    XAML: <syncfusion:GridTemplateColumn.EditTemplate> <DataTemplate DataType="viewModel:C ...

  3. swift 加载 storyboard 里的UIViewController

    let storyBoard:UIStoryboard! = UIStoryboard(name: "Main", bundle: nil) let deskVC:DeskView ...

  4. UIkit框架之UItextfield

    1.继承链:UIcontrol:UIview:UIresponder:NSObject 2.成为第一响应者:[text becomeFirstResponder];  //让该文本成为第一响应者 3. ...

  5. STL中copy算法

    STL中通过使用copy函数以提供一种方便的方式来输出容器中的元素.函数copy作为泛型算法的一部分,任何容器类型都可以使用.由于我们需要频繁的初始容器的元素,因此在继续讨论容器之前,先学习一下cop ...

  6. spring 上传文件文件的一个例子,

    /** * 类名称:UploadTest 类描述:创建人:zhang 创建时间:2015年3月13日 下午4:20:57 修改人:zhang * 修改时间:2015年3月13日 下午4:20:57 修 ...

  7. 转自CSDN-详述 Java 中的别名现象

    在任何编程语言中,赋值操作都是最常见的操作之一,Java 自然也不例外.赋值时,使用赋值操作符=,它的意思是:“将等号右边的值(右值),复制给左边的值(左值)”.右值可以是任何常数.变量或者表达式(只 ...

  8. 【论文笔记】Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition

    Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition 2018-01-28  15:4 ...

  9. SpringLog4j日志体系实现方式

    1.通过web.xml读取log4j配置文件内容 2.通过不同的配置信息,来实现不同的业务输出,注意:log4j可以写入tomcat容器,也可以写入缓存,通过第三方平台读取 #输入规则#log4j.r ...

  10. 剑指offer五之用两个栈实现队列

    一.题目 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 二.思路 1.Push操作:将数据直接压入stack1即可 2.Pop操作:将stack1中的数据全部弹 ...