Java 如何处理SWT外壳(和对话框)?
处理SWT外壳的正确方法是什么?我已经按照对话框API文档中给出的模板成功创建了一些对话框。委员会: 用户定义对话框的基本模板通常看起来像 像这样:Java 如何处理SWT外壳(和对话框)?,java,swt,eclipse-rcp,dispose,Java,Swt,Eclipse Rcp,Dispose,处理SWT外壳的正确方法是什么?我已经按照对话框API文档中给出的模板成功创建了一些对话框。委员会: 用户定义对话框的基本模板通常看起来像 像这样: public class MyDialog extends Dialog { Object result; public MyDialog (Shell parent, int style) { super (parent, style); } pu
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;
}
}
我创建的对话框在Windows上没有自己的任务栏图标,正如我所期望的那样。我现在想创建一些shell,如果我理解正确,它们将在Windows上接收自己的任务栏条目
与上述API文档中给出的方向相反,我也看到了这一点,这似乎表明使用API文档中所示的while循环是错误的做法。本文建议使用close事件侦听器来处理Shell
处理SWT外壳的正确方法是什么(在本主题中,还有对话框)?希望我能帮助解释这里发生了什么
Dialog
基本上只是一个方便的子类,因为Shell
本身不应该被子类化。如果愿意,可以创建壳,而无需使用对话框
。在这种情况下,您的MyDialog
类是一个其他人可以用来重复打开同类对话框的类
只要shell处于打开状态,这段代码就会驱动SWT事件循环(默认情况下,单击shell上的关闭按钮会处理shell):
您必须定期调用Display.readAndDispatch
,以防止SWT应用程序“锁定”。基本上,它会使应用程序正确处理来自操作系统的所有传入事件(键盘和鼠标事件、重绘事件等)readAndDispatch
基本上从应用程序的事件队列中获取事件并调用正确的侦听器。在EclipseRCP应用程序中,工作台通常负责“泵送”事件循环,您不必处理它
在此上下文中“手动”泵送事件循环的目的是防止MyDialog.open
在shell未被释放时返回,但仍然防止应用程序“挂起”。如果您的MyDialog.open
方法试图等待shell被释放,但它没有泵送事件循环,那么您的应用程序将“锁定”,因为如果没有事件循环运行,shell将永远无法得到应该被释放的通知
可以不使用此图案创建壳。下面是一个非常简单的SWT应用程序的示例,该应用程序一次打开一吨shell,只要其中至少一个shell仍然打开(我省略了包声明和导入):
希望这有助于让事情变得更清楚
编辑添加:我不完全确定为什么您的shell没有windows任务栏项,但我怀疑这与您传递到shell构造函数中的样式标志有关。我的示例中的shell没有样式标志,它们都有一个任务栏图标。感谢您提供了这一信息丰富的答案。关于任务栏图标:我已将“主窗口”设置为对话框外壳的父窗口。当您将另一个shell作为父级传递给新shell的构造函数时,新shell将不会收到任务栏图标,并且新shell将始终位于其父级之上(以便不被忽略)。任务栏(Windows 7)上仅显示将显示器作为其父级的Shell。至少,这是我的测试所建议的。
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
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();
}
}
}
}
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();
}
}
}
}