显然,所有Eclipse/SWT在管理繁忙的鼠标指示器方面都是
BusyIndicator.showWhile(Runnable synchronousStuffToDo)然而,我有一个从根本上讲是面向事件的项目,在这个项目中,“要做的事情”不会发生在一个连续的执行过程中:一个动作被命令,一个延续回调被提供给执行管理器。因此,我没有什么有意义的投入到synchronousStuffToDo运行中。
还有另一种方式,无论多么低级和笨拙,但与平台无关的方式异步地操作繁忙的指示器,这意味着两个单独的方法调用“激活它”和“禁用它”?
我应该在这个问题中添加ProgressMonitorDialog,因为它似乎遇到了同样的问题。是的,在ProgressMonitorDialog#run方法中将旋转一个内部事件循环,但是SWT循环只是我的执行管理器之一,所以链仍然会被打破。显然,没有这个类,我甚至不能显示进度监视器,除非我是从低级原语重新实现的。
发布于 2013-06-14 21:14:52
您无法使用Cursor类操作BusyIndicator。在后台Thread上运行作业时,可以调用下面的util方法来显示繁忙的图标
public static void imBusy(final boolean busy){
Display.getDefault().asyncExec(new Runnable()
{
@Override
public void run()
{
Shell shell = Display.getDefault().getActiveShell();
if(busy){ //show Busy Cursor
Cursor cursor = Display.getDefault().getSystemCursor(SWT.CURSOR_WAIT);
shell.setCursor(cursor);
}else{
shell.setCursor(null);
}
}
});
}发布于 2013-06-14 23:36:39
您的可运行程序应该等待任务完成。例如(用浏览器编写的代码,不会编译--我忽略了异常):
final Object condition = new Object();
BusyIndicator.showWhile(new Runnable() {
public void run() {
synchronized(condition) {
while (!isMyTaskDoneFlag()) {
condition.wait();
}
}
}
});
doTask(new MyTask() {
public void perform() {
try {
// Task logic
...
} finally {
// When done
setMyTaskDoneFlag();
synchronized(condition) {
condition.notify();
}
}
}
});确保任务中的所有代码路径都不要忘记取消阻塞可运行的代码。几乎同样的方法可以用于进度监视器--您可能会唤醒您的可运行状态来更新进度监视器值。
注意:您需要确保等待的runnable不会在SWT线程上执行(例如,如果正在运行监视器,则将fork设置为true ),否则应用程序将失去响应。
发布于 2016-05-06 06:34:17
我在我现在正在研究的一个较旧的SWT应用程序中找到了一个解决方案(我并不特别喜欢这个解决方案,但它很有效)。它使用BusyIndicator#showWhile,它在内部所做的同步工作是:
while (!taskDone){
if (!display.readAndDispatch() && !shell.isDisposed()) {
display.sleep();
}
taskDone = //check for task progress
//update something on the main window status bar
}我试图把它转换成更干净的东西(按照Marko的建议):
但我不确定更新状态栏的最佳方法是什么(后台任务实际上是远程调用,因此线程会被阻塞,直到线程完成)。我正在考虑有一个专门的线程来检测后台作业何时运行,并相应地更新状态栏(更新只是一条展开的虚线,没有特定于任务的内容),但是只使用一个线程似乎有点浪费。
https://stackoverflow.com/questions/17116305
复制相似问题