How do I detect that a SWT dialog has been opened and is visible?

不打扰是莪最后的温柔 提交于 2019-12-12 17:03:18

问题


I have an SWT WizardDialog with a number of pages. When this dialog first opens I have to do a check for some conditions and if those conditions are met I need to show a popup over the freshly opened dialog.

So I have this code to listen for SWT.Show event. The event listener responds to SWT.Show to conduct its tests and show a message box:

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

Except it's called too soon! The dialog is not visible when the handler is called. My message box appears before the dialog is visible and the dialog only appears when I dismiss the message box.

So clearly the SWT.Show is unreliable, at least on Windows where I'm running it. I've also tried putting this code into a ShellListener on the activation but that happens even before the SWT.Show example above.

So how do I reliably show a message box when the dialog is made visible?

Plan B is a dirty timer based hack where a timer is set to fire 200ms into the future and hope that it triggers when the dialog is visible but obviously this could introduce it's own issues.


回答1:


I'm using in similar situation (need that appStarted() is called after application window is visible) something like below.

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

Maybe You can use the same like below:

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



回答2:


Instead of hooking the SWT.Show event, you may get more luck with hooking a PaintListener on to your dialog's Composite. (You'll probably want to unhook it during the first execution.)




回答3:


What about overriding dialog.open() methodon your WizardDialog class? The first line of the overridden method would call super.open(), which would make it visible. Just put your custom code after that, in the .open() method.

The issue with the approach you're taking above appears to be that it responds to a Show event, which is simply notification that Show has been requested, not that the dialog is visible. The Show event could very well be designed to allow you to know when something is about to be shown, and take some action before that happens, as you've experienced.




回答4:


I know that this is an old thread. But in case someone finds it useful, I found that overriding Dialog.create() rather than Dialog.open() worked for me.




回答5:


The code of marioosh can be further improved, by storing the ShellAdapter in a variable.

Remove the ShellAdapter when the listener is triggered for the first time.

The variable started is no longer needed.

The statement s.setVisible(true); is not necessary, because this event is just triggered when the shell gets visible.

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


来源:https://stackoverflow.com/questions/7387818/how-do-i-detect-that-a-swt-dialog-has-been-opened-and-is-visible

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!