您的位置:首页 > 其它

怎么正确的使用SWT进度条

2008-04-01 18:16 246 查看

怎么正确的使用SWT进度条

摘要
使用进度条监视器并不像看起来的那么简单,在使用时很容易犯错。这取决于各种因素,像底层实现,显示方式,是否被设定固定数目的工作条目,是否使用了SubProgressMonitor 嵌套,等等。结果可能是完全没问题,也可能是 让人挠头,或者彻底不可用。

本文将指导怎样有效的使用进度条监视器。

使用进度条监视器

在许多简单的惯例中,有一条是“只知道所知道的,并且仅限于此”。这就是说,不能假设完全了解你所不知道的事情。就像,你不能想当然的认为进度条监视器就是你在IDE中看到的那些图片样子的东西。

IProgressMonitor

通常,所有的进度条操作都是通过IProgressMonitor接口.进度条监视器具有4中状态,通过接口只可以测到一种状态(当监视器被取消时)。状态的改变是通过如下方法的作用: beginTask(), done() and setCanceled(). PRISTINE
IProgressMonitor实例被初始化之后,方法beginTask() 被调用之前的状态。
IN_USE
方法beginTask()被调用之后的状态,这里要注意 beginTask()只能被调用一次,
FINISHED
done()被调用之后的状态, 它也只能调用一次,并且只能在 beginTask()之后调用。
CANCELED
进度条被取消之后的状态。

要以以下的模式使用进度条:
monitor = ?  		// 获取进度条实例,现在处于 pristine 状态
  		try
	{
	monitor.beginTask(?
	// 执行工作任务
	}
finally
	{
	monitor.done()
	}
The 一定到保证 done() 最后被执行。

子任务用代理使用进度条监视器

beginTask()被调用不要多于一次,这种错误经常发生。进度条被传给子任务,子任务没有意识到进度条已经执行了beginTask(),还是按照规定的契约,执行beginTask()方法。除非子任务对此了解,否则传递进度条实例是十分错误的。一般情况下,接受到进度条实例的代码应该假设此实例自己会遵守beginTask()/done()契约。如果子任务也需要进度条,就应该使用SubProgressMonitor作为代理,封装传入的进度条实例。

如下为样例:
monitor = ?// 获取进度条实例

try
	{
	monitor.beginTask(?
		// 执行任务
	?BR>	// 创建一个子任务
	someThing.doWork(new SubProgressMonitor(monitor,?)
		// // 创建右一个子任务	
	anotherThing.doWork(new SubProgressMonitor(monitor,?)
	}
finally
	{
	monitor.done()
	}
每一个doWork()调用得到一个新的SubProgressMonitor 实例。

管理条目个数

如果确实不知道确切的条目总数,不要随意猜测数字。如果猜大了,数字会走的很慢,然后突然到达100%;如果猜小了,那么会很快到达终点,并且永远停在那里。没有确切总数的话,填写 IProgressMonitor.UNKNOWN就可以了。

怎样调用 beginTask() 和worked()

通常你可以通过两种方式得出你究竟要处理多少条目:一是调用许多不同的方法来得到结果,二是在一个集合中为每一个实例调用同一个方法。每种方式你都可以知道总的条目数(方法的个数或集合的大小)。

你应该将按比例测量出你的总数。如果总数是3 (每个条目工作为worked(1)),你可以把比例定为1000,总数为3000, (每个条目工作为worked(1000) ). 当你要通过SubProgressMonitor将工作传递到子任务中,就要应用这种方式。因为子任务内部的总数和外部是不同的,也许比你定的总数大许多。你要给它们一些缓冲润滑的空间。这样可以避免进度条执行时视觉上的便扭。

样例:
monitor = ?	// 取到进度条监视器
int total = 3 // 总数为3
try
	{
	monitor.beginTask(total)
	
		// 条目1
	this.doPart1()
	monitor.worked(1)

	// 条目 2
	this.doPart2()
		monitor.worked(1)

	// 条目 3
	this.doPart3()
	monitor.worked(1)
	}
finally
		{
	monitor.done()
	}
这里没有必要按比例放大,也没有集合动态计算。

更详细的样例:
monitor = ?		
int total = thingyList.size() * 3 + 2
try
	{
	monitor.beginTask(total)
	
	// 条目 1
		this.doBeforeAllThingies()
	monitor.worked(1)
		
	// 条目 2 to 倒数第二个
	for (Thingy t : thingyList)
			{
		t.doThisFirst()
		monitor.worked(1)
		t.thenDoThat()
		monitor.worked(1)
			t.lastlyDoThis()
		monitor.worked(1)
		}

	// 最后一条 
	this.doAfterAllThingies()
		monitor.worked(1)
	}
finally
	{
	monitor.done()
	}

混合使用子任务

在使用子任务的时候,子任务的总数就是分配给它的比例数。
monitor = ?	
int scale = 1000
	int total = 3 
try
	{
	monitor.beginTask(total * scale)
		
	// item 1
	this.doPart1()
	monitor.worked(1 * scale)
	
	// item 2
	this.doPart2(new SubProgressMonitor(monitor, 1 * scale)) //分配一个条目
		monitor.worked(1 * scale) // 这里是不需要的,因为任务的管理有子任务负责

			// 条目 3
	this.doPart3()
	monitor.worked(1 * scale)
	}
finally
	{
	monitor.done()
			}
You worked().



不要将 IProgressMonitor.UNKNOWN 传给创建的 SubProgressMonitor()

子任务进度条的实现只是盲目的使用传入的总数进行计算,当它接受到的是一个负值(IProgressMonitor.UNKNOWN为-1) 它也是按照惯例来进行计算,所以你看到的结果是进度条往回走。 IProgressMonitor.UNKNOWN不能在子任务进度条中使用,但是在父进度条中使用没有这种问题。

取消

上面的例子中,都没有判断进度条是否被取消。在实际使用中,推荐要及时的进行判断。
monitor = ?	
try
	{
	monitor.beginTask(thingyList.size())
	
	for (Thingy t : thingyList)
		{
		if(monitor.isCanceled())
			throw new OperationCanceledException();
		t.doSomething()
		monitor.worked(1)		
		}
	}
finally
	{
	monitor.done()
}

The 空进度条

这样可以使调用者不用必须传入monitor,只要输入null 就可以了。
public void doIt(IProgressMonitor monitor)
{
	
	if(monitor == null)
		monitor = new NullProgressMonitor();

	try
	{
		monitor.beginTask(thingyList.size())
	
		for (Thingy t : thingyList)
			{
			if(monitor.isCanceled())
				throw new OperationCanceledException();
			t.doSomething()
			monitor.worked(1)		
			}
	}
finally
	{
		monitor.done()
	}	
}

结论

只要遵循这些规则,在使用进度条的时候就不会碰到麻烦。如果不信邪,想当然的用,迟早会出现奇怪的视觉显示,你的客户又要不停的抱怨了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: