我正在通过示例初学者指南“Eclipse 4 Plug-in Development”中的练习。我进入了标题为“操作时间 - 将项目添加到托盘”的部分,当我运行测试实例时,我开始看到这样的错误:
org.eclipse.swt.SWTError: Not implemented [multiple displays]
at org.eclipse.swt.SWT.error(SWT.java:4308)
at org.eclipse.swt.widgets.Display.checkDisplay(Display.java:760)
at org.eclipse.swt.widgets.Display.create(Display.java:896)
at org.eclipse.swt.graphics.Device.<init>(Device.java:157)
我一直在阅读有关此错误消息的一些参考资料,但我仍然不确定我能做些什么。
练习中指定的更改会在“Activator”类的“start”和“stop”方法中调用“Display.getDefault()”,这类方法扩展了AbstractUIPlugin。我确认注释掉这些新更改会删除错误。我还尝试了将“Display.getDefault()”存储为实例var并重复使用的简单更改,而不是每次在“start”和“stop”中调用“Display.getDefault()”。这没有任何影响(我不知道这是不是一个好主意)。
这是该类的当前状态,其中一些旧块已注释掉:
public class Activator extends AbstractUIPlugin {
private TrayItem trayItem;
private Image image;
private Display display;
public static final String PLUGIN_ID = "com.packtpub.e4.clock.ui"; //$NON-NLS-1$
private static Activator plugin;
public void setDisplay(Display display) {this.display = display;}
public Display getDisplay() {return display;}
public Activator() {}
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
// final Display display = Display.getDefault();
setDisplay(Display.getDefault());
getDisplay().asyncExec(new Runnable() {
public void run() {
image = new Image(getDisplay(), Activator.class
.getResourceAsStream("/icons/sample.gif"));
Tray tray = getDisplay().getSystemTray();
if (tray != null && image != null) {
trayItem = new TrayItem(tray, SWT.NONE);
trayItem.setToolTipText("Hello World");
trayItem.setVisible(true);
trayItem.setText("Hello World");
// trayItem.setImage(new Image(trayItem.getDisplay(),
// Activator.class.getResourceAsStream("/icons/sample.gif")));
trayItem.setImage(image);
}
}
});
}
public void stop(BundleContext context) throws Exception {
if (trayItem != null && !trayItem.isDisposed()) {
// Display.getDefault().asyncExec(new Runnable() {
getDisplay().asyncExec(new Runnable() {
public void run() {
if (trayItem != null && !trayItem.isDisposed())
trayItem.dispose();
}
});
}
if (image != null && !image.isDisposed()) {
// Display.getDefault().asyncExec(new Runnable() {
getDisplay().asyncExec(new Runnable() {
public void run() {
if (image != null && !image.isDisposed())
image.dispose();
}
});
}
}
public static Activator getDefault() {return plugin;}
public static ImageDescriptor getImageDescriptor(String path) {
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
}
更新:
当尝试创建多个“Display”对象时,会出现这种情况,我在Display类的两个构造函数中设置断点。
由于在我的Activator类中调用了“Display.getDefault()”,我点击了断点,但是在我的“start”方法完成之后,我也用以下堆栈点击它:
Thread [main] (Suspended (breakpoint at line 500 in Display))
Display.<init>(DeviceData) line: 500
Workbench.createDisplay() line: 714
PlatformUI.createDisplay() line: 161
IDEApplication.createDisplay() line: 153
IDEApplication.start(IApplicationContext) line: 95
EclipseAppHandle.run(Object) line: 196
EclipseAppLauncher.runApplication(Object) line: 110
EclipseAppLauncher.start(Object) line: 79
EclipseStarter.run(Object) line: 344
EclipseStarter.run(String[], Runnable) line: 179
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 606
Main.invokeFramework(String[], URL[]) line: 622
Main.basicRun(String[]) line: 577
Main.run(String[]) line: 1410
Main.main(String[]) line: 1386
当我从这个断点恢复时,我看到“多个显示”错误。因此,错误不会发生在我的班级中,它会在稍后发生,当时正在创建另一个人物。
更新:
当我继续阅读本书中的练习时,我在自定义视图的“createPartControl()”方法中遇到了另一个调用“Display.getDefault()”的代码块。我想知道这里会发生什么。使用我在两个Display构造函数中的现有断点以及“getDefault()”中的一个断点,并在我的“Activator”类中注释掉有问题的代码,我在启动测试实例时看到的是第一次调用Display构造函数就在此之前的堆栈跟踪中,来自“IDEApplication.createDisplay()”。之后,它进入了我的视图创建,但是对“Display.getDefault()”的调用没有创建新的显示,因为它已经存在。
从我到目前为止所看到的,将代码放入调用“Display.getDefault()”的bundle Activator类似乎不是一个好主意,因为当IDEApplication完全启动时,它会强制执行显示的创建,将失败。