Как я могу использовать этапы SWT и JavaFx в одном потоке? - PullRequest
0 голосов
/ 10 октября 2019

У меня есть приложение с JavaFX Stage и SWT Shell. На этапе JavaFX существуют контроллеры, которые изменяют свойства виджетов SWT в командной консоли и некоторых контроллеров JaveFX, информирующих об изменениях в виджетах SWT. Конечно, все с JavaFX должно происходить в потоке приложения JavaFx, и все с SWT-виджетами должно происходить в потоке SWT.

Сначала я попытался создать по одному потоку для каждого и переключать поток при каждом переключении контекста. это было очень раздражающим, и я решил больше не следовать этому подходу. Вместо этого создайте окно SWT внутри потока приложения JavaFX, чтобы два интерфейса пользователя работали в одном потоке. Все работает нормально, за исключением одной вещи:

while (!shell.isDisposed()) {
    if (!display.readAndDispatch())
        display.sleep();
}

SWT нуждается в этом фрагменте, в противном случае ни один из виджетов не реагирует на события, и SWT требует, чтобы это было в том же потоке, как и все остальное. Но этот фрагмент блокируется, поэтому, как только я его использую, JavaFX зависает.

Я знаю, что наличие окон SWT и JavaFX, вероятно, очень странный вариант использования, но есть ли решение для этого?

Просто чтобы уточнить:

  • Мне не нужны узлы JavaFX внутри виджетов SWT

  • Мне не нужны виджеты SWT внутри узлов JavaFX.

1 Ответ

2 голосов
/ 29 октября 2019

SWT и JavaFX могут работать в одном потоке. Небольшая хитрость для достижения этой цели заключается в создании фиктивного FXCanvas экземпляра перед вызовом любого другого кода JavaFX. FXCanvas обычно используется для встраивания элементов управления FX в SWT;даже если вам это не нужно, конструктор FXCanvas правильно инициализирует JavaFX для работы в режиме взаимодействия SWT.

В приведенном ниже фрагменте кода демонстрируется работа оболочки SWT и этапа 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();
        }
    }
...