我有一个带有JavaFX Stage和SWT Shell的应用程序。 JavaFX阶段中有一些控件可以更改命令行管理程序中SWT小部件的属性,有些JaveFX控件可以通知SWT小部件中的更改。当然,JavaFX的所有操作都必须在JavaFx应用程序线程中发生,而SWT小部件的所有操作都必须在SWT线程中发生。
我首先尝试为每个线程分配一个线程,并在切换上下文时切换线程。这很烦人,我决定不再采用这种方法。而是在JavaFX Application线程内创建SWT窗口,以便两个UI在同一线程上运行。除了一件事情以外,其他所有内容都可以正常工作]
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
SWT需要此代码段,否则,所有小部件都不会对事件做出反应,SWT则需要将其与其他所有对象都放在同一线程上。但是此代码段已被阻止,因此,一旦我使用它,JavaFX就会冻结。
我知道拥有SWT和JavaFX窗口可能是一个非常奇怪的用例,但是对此有解决方案吗?
仅作说明:
我不希望SWT小部件内有JavaFX节点
我不希望JavaFX节点内有SWT小部件。
SWT和JavaFX可以在同一线程中操作。实现此目的的一个小技巧是在调用任何其他JavaFX代码之前创建一个虚拟FXCanvas实例。 FXCanvas通常用于将FX控件嵌入到SWT中。即使您不需要,FXCanvas构造函数也会正确初始化JavaFX以在SWT互操作性模式下工作。
下面的代码片段演示了SWT shell和JavaFX阶段如何协同工作。 SWT和JavaFX按钮单击处理程序都在JavaFX Application线程上执行。
public static void main(String[] args) {
Display display = Display.getDefault();
new FXCanvas(new Shell(), SWT.NONE);
Stage primaryStage = new Stage();
Button fxbutton = new Button("JavaFX button");
Scene scene = new Scene(fxbutton);
fxbutton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> System.out.println("FX event, thread=" + Thread.currentThread().getName()));
primaryStage.setScene(scene);
primaryStage.show();
Shell shell = new Shell(display, SWT.CLOSE);
shell.setLayout(new FillLayout());
org.eclipse.swt.widgets.Button swtbutton = new org.eclipse.swt.widgets.Button(shell, SWT.PUSH);
swtbutton.setText("SWT button");
swtbutton.addListener(SWT.Selection, event -> System.out.println("SWT event, thread=" + Thread.currentThread().getName()));
shell.open();
shell.pack();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}