使用SWT显示父模态对话框

13

AWT/Swing允许显示应用程序模式(阻止整个应用程序)和父模式(仅阻止父级)对话框。我如何使用SWT实现相同的效果?

1个回答

26
为了阻塞整个应用程序,您可以创建具有样式SWT.APPLICATION_MODAL的对话框Shell,打开它,然后泵送UI事件直到对话框被销毁。
Display display = Display.getDefault();
Shell dialogShell = new Shell(display, SWT.APPLICATION_MODAL);
// populate dialogShell
dialogShell.open();
while (!dialogShell.isDisposed()) {
    if (!display.readAndDispatch()) {
        display.sleep();
    }
}
如果您想只阻止父级输入,可以尝试使用样式SWT.PRIMARY_MODAL,但是Javadocs指定(对于其他模态样式也是如此),这只是一个提示;也就是说,不同的SWT实现可能无法完全相同地处理它。同样,我不知道任何一种实现会支持SWT.SYSTEM_MODAL样式。

更新:回答第一条评论

如果您同时打开了两个或更多的主模态框,则无法使用技巧来推送事件,直到模态框关闭,因为它们可以按任何顺序关闭。代码将运行,但在当前对话框关闭和所有在其之后打开的这样的对话框之后,执行将恢复到while循环之后。在这种情况下,我会在每个对话框上注册一个DisposeListener以获得它们关闭时的回调。类似这样:

void run() {
    Display display = new Display();
    Shell shell1 = openDocumentShell(display);
    Shell shell2 = openDocumentShell(display);

    // close both shells to exit
    while (!shell1.isDisposed() || !shell2.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }
    display.dispose();
}

Shell openDocumentShell(final Display display) {
    final Shell shell = new Shell(display, SWT.SHELL_TRIM);
    shell.setLayout(new FillLayout());
    Button button = new Button(shell, SWT.PUSH);
    button.setText("Open Modal Dialog");
    button.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            System.out.println("Button pressed, about to open modal dialog");
            final Shell dialogShell = new Shell(shell, SWT.PRIMARY_MODAL | SWT.SHEET);
            dialogShell.setLayout(new FillLayout());
            Button closeButton = new Button(dialogShell, SWT.PUSH);
            closeButton.setText("Close");
            closeButton.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent e) {
                    dialogShell.dispose();
                }
            });
            dialogShell.setDefaultButton(closeButton);
            dialogShell.addDisposeListener(new DisposeListener() {
                @Override
                public void widgetDisposed(DisposeEvent e) {
                    System.out.println("Modal dialog closed");
                }
            });
            dialogShell.pack();
            dialogShell.open();
        }
    });
    shell.pack();
    shell.open();
    return shell;
}

感谢您的回答。当在两个不同的窗口中使用SWT.PRIMARY_MODAL对话框时,事件循环应该如何设计,以便对话框不会阻塞另一个窗口?也许您可以提供一个完整的工作示例,其中包含两个带有一个父模态对话框的窗口?提前致谢。 - Mot
2
顺便说一下,SWT.SHEET样式特别适用于这些PRIMARY_MODAL对话框。在Mac OS X上,它们会导致对话框似乎从父级的标题栏中出现,并与父级可见地连接,清楚地表明它仅阻止与其父级的UI交互。不知道其他平台会发生什么... - Jean-Philippe Pellet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接