2011-09-12 107 views
3

我有一个页面的SWT WizardDialog。当这个对话框第一次打开时,我必须检查一些条件,如果满足这些条件,我需要在新打开的对话框上显示一个弹出窗口。如何检测SWT对话框是否已打开并可见?

所以我有这个代码来监听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示例之前。

那么当对话框变得可见时,如何可靠地显示消息框呢?

B计划是一个基于脏计时器的黑客攻击,其中一个计时器被设置为在将来触发200ms,并希望在对话框可见时触发,但显然这可能会引入它自己的问题。

回答

1

怎样在WizardDialog课程上覆盖dialog.open()方法?重写方法的第一行将调用super.open(),这将使其可见。然后在.open()方法中放上您的自定义代码。

与你上面采用的方法的问题似乎是,它响应一个显示事件,这简直是通知显示已请求,不是对话框可见。 Show事件的设计可以让你知道什么时候会显示什么,并在发生之前采取一些行动,就像你经历过的一样。

+1

同意100% - 虽然我认为你的意思是写super.open()。 –

+0

啊,是的。更正了它 - 谢谢。 – jefflunt

+3

我无法重写Window.open()(这是打开对话框的方法),因为对话框被阻塞。 open()方法调用shell.open(),然后调用runEventLoop()方法,这是一种私有方法,用于泵送消息,直到对话框被丢弃。如果runEventLoop()被保护,我可以在那里插入一些东西,但因为它不是我不能。目前我使用计时器来弹出消息框,但显然这不符合我的喜好。 – locka

2

取代挂钩SWT.Show事件,您可能会将更多的运气挂在对话框Composite上。 (你可能想在第一次执行时解除它)。

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(); 
0

我知道这是一个古老的线程。但是如果有人发现它很有用,我发现重写Dialog.create()而不是Dialog.open()对我有用。

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); 
    } 
}