我如何在同一线程中使用 SWT Shell 和 JavaFx 阶段?
How can i use SWT Shells and JavaFx stages in the same Thread?
我有一个带有 JavaFX Stage 和 SWT 的应用程序 Shell。 JavaFX 阶段中有一些控件可以更改 Shell 中 SWT 小部件的属性,还有一些 JaveFX 控件可以通知 SWT 小部件中的更改。
当然,JavaFX 的一切都必须在 JavaFx 应用程序线程中发生,而 SWT 小部件的一切都必须在 SWT 线程中发生。
我首先尝试为每个线程设置一个线程,并在切换上下文时切换线程。这很烦人,我决定不再采用这种方法。
相反,在 JavaFX 应用程序线程内创建 SWT window,以便两个 UI 运行 在同一线程上。除了一件事
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
SWT 需要这个片段,否则没有任何小部件对事件做出反应,SWT 也需要这个像其他所有东西一样在同一个线程上。但是这个片段是阻塞的,所以我一使用它,JavaFX 就会冻结。
我知道使用 SWT 和 JavaFX windows 可能是一个非常奇怪的用例,但是有解决方案吗?
澄清一下:
我不想在 SWT Widgets 中使用 JavaFX 节点
我不想在 JavaFX 节点中使用 SWT 小部件。
SWT 和JavaFX 可以在同一个线程中运行。实现这一点的一个小技巧是在调用任何其他 JavaFX 代码之前创建一个虚拟 FXCanvas 实例。 FXCanvas 通常用于将 FX 控件嵌入到 SWT 中;即使您不需要它,FXCanvas 构造函数也会正确初始化 JavaFX 以在 SWT 互操作模式下工作。
下面的代码片段演示了 SWT shell 和 JavaFX 阶段的协同工作。 SWT 和 JavaFX 按钮单击处理程序都在 JavaFX 应用程序线程上执行。
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();
}
}
我有一个带有 JavaFX Stage 和 SWT 的应用程序 Shell。 JavaFX 阶段中有一些控件可以更改 Shell 中 SWT 小部件的属性,还有一些 JaveFX 控件可以通知 SWT 小部件中的更改。 当然,JavaFX 的一切都必须在 JavaFx 应用程序线程中发生,而 SWT 小部件的一切都必须在 SWT 线程中发生。
我首先尝试为每个线程设置一个线程,并在切换上下文时切换线程。这很烦人,我决定不再采用这种方法。 相反,在 JavaFX 应用程序线程内创建 SWT window,以便两个 UI 运行 在同一线程上。除了一件事
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
SWT 需要这个片段,否则没有任何小部件对事件做出反应,SWT 也需要这个像其他所有东西一样在同一个线程上。但是这个片段是阻塞的,所以我一使用它,JavaFX 就会冻结。
我知道使用 SWT 和 JavaFX windows 可能是一个非常奇怪的用例,但是有解决方案吗?
澄清一下:
我不想在 SWT Widgets 中使用 JavaFX 节点
我不想在 JavaFX 节点中使用 SWT 小部件。
SWT 和JavaFX 可以在同一个线程中运行。实现这一点的一个小技巧是在调用任何其他 JavaFX 代码之前创建一个虚拟 FXCanvas 实例。 FXCanvas 通常用于将 FX 控件嵌入到 SWT 中;即使您不需要它,FXCanvas 构造函数也会正确初始化 JavaFX 以在 SWT 互操作模式下工作。
下面的代码片段演示了 SWT shell 和 JavaFX 阶段的协同工作。 SWT 和 JavaFX 按钮单击处理程序都在 JavaFX 应用程序线程上执行。
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();
}
}