我有一个包含许多页面的SWT WizardDialog。当这个对话框第一次打开时,我必须检查一些条件,如果满足这些条件,我需要在刚打开的对话框上显示一个弹出窗口。
所以我有这个代码来监听SWT.Show事件。事件监听器响应SWT.Show进行测试并显示一个消息框:
final WizardDialog dialog = new WizardDialog(shell, wizard);
dialog.setTitle("New Wizard");
dialog.create();
dialog.getShell().addListener(SWT.Show, new Listener()
{
private boolean firstShowing = true;
@Override
public void handleEvent(Event event)
{
if (firstShowing && someConditionExists())
{
MessageBox messageBox = new MessageBox(dialog.getShell(), SWT.OK
| SWT.ICON_WARNING);
messageBox.setMessage("Test");
messageBox.open();
firstShowing = false;
}
}
});
dialog.open();
除了它太快了!调用处理程序时,该对话框不可见。在对话框可见之前出现我的消息框,只有当我关闭消息框时才会出现对话框。
很明显SWT.Show是不可靠的,至少在我运行它的Windows上。我也尝试在激活时将此代码放入ShellListener中,但这种情况甚至发生在上面的SWT.Show示例之前。
那么当对话框可见时,如何可靠地显示消息框?
Plan B是一个基于脏计时器的hack,其中一个计时器被设置为在未来200ms触发,并希望它在对话框可见时触发,但显然这可能会引入它自己的问题。
答案 0 :(得分:4)
我在类似情况下使用(需要在应用程序窗口可见后调用appStarted()
),如下所示。
public class App extends ApplicationWindow {
@Override
protected Control createContents(Composite parent) {
// ...
getShell().addShellListener(new ShellAdapter() {
@Override
public void shellActivated(ShellEvent shellevent) {
if (!started) {
Shell s = (Shell) shellevent.getSource();
s.setVisible(true);
appStarted();
started = true;
}
}
});
}
}
也许您可以使用如下所示:
final WizardDialog dialog = new WizardDialog(shell, wizard);
dialog.setTitle("New Wizard");
dialog.create();
dialog.getShell().addShellListener(new ShellAdapter() {
@Override
public void shellActivated(ShellEvent shellevent) {
if (firstShowing && someConditionExists()) {
Shell s = (Shell) shellevent.getSource();
s.setVisible(true);
MessageBox messageBox = new MessageBox(dialog.getShell(), SWT.OK | SWT.ICON_WARNING);
messageBox.setMessage("Test");
messageBox.open();
firstShowing = false;
}
}
});
dialog.open();
答案 1 :(得分:2)
您可以将SWT.Show
挂钩到对话框的PaintListener
,而不是挂钩Composite
事件。 (你可能想在第一次执行时取消它。)
答案 2 :(得分:1)
在dialog.open()
课程中覆盖WizardDialog
方法怎么样?重写方法的第一行将调用super.open()
,这将使其可见。只需在.open()
方法中添加自定义代码。
您上面采用的方法的问题似乎是它响应了Show 事件,这只是通知已请求显示,并非对话框可见即可。 Show事件可以很好地设计为让你知道什么东西即将被展示,并在你发生之前采取一些行动。
答案 3 :(得分:1)
我知道这是一个老话题。但是如果有人发现它有用,我发现重写Dialog.create()而不是Dialog.open()对我有效。
答案 4 :(得分:1)
太快了!
我最近也遇到了同样的麻烦。代码执行得太早 - 我的上传操作(我想在某些情况下自动启动)在页面显示之前就开始了。
出现这种情况是因为只有在 SWT.SHOW 侦听器或继承的 setVisible() 方法中的代码完成后才能显示页面。
@Override
public void setVisible(boolean visible) {
if (visible) {
org.eclipse.ui.progress.UIJob("Auto start the upload") {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (isAutoStartQcUploadSelected)
startUpload();
return Status.OK_STATUS;
}
};
uiJob.schedule();
}
super.setVisible(visible);
}
org.eclipse.ui.progress.UIJob 如所描述的 FAQ_Can_I_make_a_job_run_in_the_UI_thread 已经解决了这个问题。
PS:是的,我知道这是一个老问题:-) 但它是 google 提出的第一个,缺少 UI Job 的提示。
答案 5 :(得分:0)
通过将ShellAdapter
存储在变量中,可以进一步改进marioosh的代码。
首次触发侦听器时删除ShellAdapter
。
不再需要变量started
。
语句s.setVisible(true);
不是必需的,因为只有在shell可见时才会触发此事件。
public class App extends ApplicationWindow {
@Override
protected Control createContents(Composite parent) {
// ...
ShellAdapter shellActivatedAdapter = new ShellAdapter() {
@Override
public void shellActivated(ShellEvent shellevent) {
shellevent.getSource().removeShellListener(shellActivatedAdapter);
appStarted();
}
};
getShell().addShellListener(shellActivatedAdapter);
}
}