处理SWT炮弹的正确方法是什么?我按照Dialog API文档中给出的模板创建了一些成功的Dialogs。 SWT API for Dialog says:
用户定义对话框的基本模板通常看起来很像 像这样:
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文档中给出的说明相反,我还看到an article似乎暗示如API文档中所示的while循环是错误的方法。相反,本文建议使用close事件监听器来处理Shell。
处理SWT炮弹的正确方法是什么(当涉及主题时,也是对话)?
答案 0 :(得分:10)
希望我能帮助解释这里发生的事情。
Dialog
基本上只是一个方便的子类类,因为Shell
本身不应该是子类。如果您愿意,可以根本不使用Dialog
创建shell。在这种情况下,您的MyDialog
类是其他人可以用来重复打开相同类型对话框的类。
只要shell打开,这段代码就会驱动SWT事件循环(单击shell上的关闭按钮会默认配置shell):
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
您必须定期致电Display.readAndDispatch
以防止您的SWT应用程序“锁定”。基本上它会导致应用程序正确处理来自操作系统的所有传入事件(键盘和鼠标事件,重新绘制事件等)。 readAndDispatch
基本上从应用程序的事件队列中获取一个事件并调用正确的侦听器。在Eclipse RCP应用程序中,工作台通常负责“抽取”事件循环,您不必乱用它。 Here's a little more info about the event loop.
在此上下文中“手动”抽取事件循环的目的是防止MyDialog.open
在未处置shell时返回,但仍使应用程序“挂起”。如果你的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();
}
}
}
}
请注意,我在每个shell中添加DisposeListener
,以便在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();
}
}
}
}
希望这有助于使事情变得更加清晰!
编辑添加:我不完全确定为什么你没有为你的shell获取一个Windows任务栏项,但我怀疑它与你传递给shell的构造函数的样式标志有关。我的示例中的shell没有样式标志,它们都有一个任务栏图标。