如何处理SWT Shell(和Dialogs)?

But*_*840 3 java swt dispose eclipse-rcp

什么是处理SWT炮弹的正确方法?我按照Dialog API文档中给出的模板创建了一些成功的Dialogs.对话SWT API说:

用户定义对话框的基本模板通常如下所示:

 public class MyDialog extends Dialog {
        Object result;

        public MyDialog (Shell parent, int style) {
                super (parent, style);
        }
        public MyDialog (Shell parent) {
                this (parent, 0); // your default style bits go here (not the Shell's style bits)
        }
        public Object open () {
                Shell parent = getParent();
                Shell shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
                shell.setText(getText());
                // Your code goes here (widget creation, set result, etc).
                shell.open();
                Display display = parent.getDisplay();
                while (!shell.isDisposed()) {
                        if (!display.readAndDispatch()) display.sleep();
                }
                return result;
        }
 }
Run Code Online (Sandbox Code Playgroud)

我创建的对话框在Windows上没有自己的任务栏图标,正如我期望的对话框.我现在想创建一些Shell,如果我理解正确在Windows上收到自己的任务栏条目?

与上述API文档中给出的说明相反,我还看到一篇文章似乎暗示如API文档中所示的while循环是错误的方法.相反,本文建议使用close事件侦听器来处理Shell.

处理SWT炮弹的正确方法是什么(当谈到主题时,对话也是如此)?

Mik*_*els 10

希望我能帮助解释这里发生的事情.

Dialog基本上只是一个方便的子类类,因为Shell它本身不应该是子类.Dialog如果需要,您可以根本不创建shell .在这种情况下,您的MyDialog类是其他人可以用来重复打开相同类型的对话框的类.

只要shell打开,这段代码就会驱动SWT事件循环(单击shell上的关闭按钮会默认配置shell):

            while (!shell.isDisposed()) {
                    if (!display.readAndDispatch()) display.sleep();
            }
Run Code Online (Sandbox Code Playgroud)

您必须Display.readAndDispatch定期致电以防止您的SWT应用程序"锁定".基本上它会导致应用程序正确处理来自操作系统的所有传入事件(键盘和鼠标事件,重新绘制事件等).readAndDispatch基本上从应用程序的事件队列中获取一个事件并调用正确的侦听器.在Eclipse RCP应用程序中,工作台通常负责"抽取"事件循环,您不必乱用它.这里有关于事件循环的更多信息.

在此上下文中"手动"泵送事件循环的目的是防止MyDialog.open在未处置外壳时返回,但仍使应用程序不"挂起".如果你的MyDialog.open方法试图等待shell处理,但是它没有引发事件循环,你的应用程序将"锁定",因为没有事件循环运行,shell无法通知它应该被处置!

可以在不使用此模式的情况下创建shell.这是一个非常简单的SWT应用程序的例子,它可以同时打开大量的shell并且只要其中至少有一个仍然打开就会一直运行(我省略了包声明和导入):

public class Shells {
    private static int numDisposals = 0;

    public static void main(String[] args) {
        Display d = Display.getDefault();

        for (int i = 0; i < 5; i++) {
            Shell s = new Shell(d);
            s.open();
            s.addDisposeListener(new DisposeListener() {
                @Override
                public void widgetDisposed(DisposeEvent arg0) {
                    numDisposals++;
                }
            });
        }

        while (numDisposals < 5) {
            while (!d.readAndDispatch()) {
                d.sleep();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我DisposeListener向每个shell 添加一个,以便在关闭shell时执行某些操作.您还可以使用IShellListener更直接地侦听close事件,甚至实际阻止它(例如,如果shell包含未保存的工作,您可能想要这样做).这是对第一个启动5个shell并随机阻止你关​​闭它们的程序的一个恼人的修改:

public class Shells {
    private static Random r = new Random();
    private static int numDisposals = 0;

    public static void main(String[] args) {
        Display d = Display.getDefault();

        for (int i = 0; i < 5; i++) {
            Shell s = new Shell(d);
            s.open();
            s.addShellListener(new ShellAdapter() {
                @Override
                public void shellClosed(ShellEvent e) {
                    boolean close = r.nextBoolean();
                    if (close) {
                        System.out.println("Alright, shell closing.");
                    } else {
                        System.out.println("Try again.");
                    }
                    e.doit = close;
                }
            });
            s.addDisposeListener(new DisposeListener() {
                @Override
                public void widgetDisposed(DisposeEvent arg0) {
                    numDisposals++;
                }
            });
        }

        while (numDisposals < 5) {
            while (!d.readAndDispatch()) {
                d.sleep();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这有助于使事情变得更加清晰!


编辑添加:我不完全确定为什么你没有为你的shell获取一个Windows任务栏项,但我怀疑它与你传递给shell的构造函数的样式标志有关.我的示例中的shell没有样式标志,它们都有一个任务栏图标.