Статьи

Интеграция JavaFX и Swing (пересмотренный)

Я только что закончил переписывать компонент моего приложения, который использовал Swing, а теперь использует JavaFX, в результате я получил компонент JavaFX, который интегрируется с большим приложением Swing. Это большое приложение, и переписывание заняло у меня некоторое время, в конце концов, все работало нормально, и я рад, что сделал это.

Причины, по которым вы можете захотеть сделать это в своем приложении Swing

Возможно, вы захотите переписать свое приложение Swing и изменить его на использование JavaFX. Самый простой способ — сделать это постепенно, меняя каждый компонент за раз. Для этого необходимо интегрировать каждый из недавно измененных компонентов JavaFX с остальным приложением Swing.

Я резюмирую, почему вы можете начать переписывать свое приложение с Swing на JavaFX:

  • Это будущее

Swing в значительной степени мертв в том смысле, что он не получит дальнейшего развития. JavaFX — это новый инструментарий пользовательского интерфейса для Java, он лучше подготовлен к будущему с такими вещами, как сенсорная поддержка, 3D, встроенная поддержка анимации, воспроизведение видео и аудио и т. Д.

  • Вероятная будущая поддержка мобильных устройств: Android, IOS…

Уже существует работающий прототип, который позволяет переносить приложения javafx на IOS под названием RoboVM — http://www.robovm.org/ . По мере того, как все больше и больше JavaFX будут открываться с открытым исходным кодом, RoboVM получит лучший результат, и с этим открытым исходным кодом, вероятно, появятся другие утилиты, которые позволят порты для других сред.

  • Это твердое тело

JavaFX — это хорошо разработанный инструментарий с быстро растущим темпом, блестящим будущим и набором хороших бесплатных инструментов для пользовательского интерфейса. Кроме того, в отличие от прошлого, Oracle придает большое значение обратной связи с разработчиками, изменяя и адаптируя свои API для достижения своих целей.

  • Это довольно

В отличие от Swing, не считая сторонних библиотек, что само по себе было некрасиво, JavaFX выглядит хорошо с самого начала, особенно новый скин Modena, выходящий на JavaFX 8: http://fxexperience.com/2013/03/modena-theme-update / -. Учитывая, что в наше время пользователи ожидают хорошо выглядящих, хорошо разработанных приложений, это довольно хороший момент.

  • Приятные дополнения

Некоторые приятные дополнения, такие как API диаграмм, встроенный браузер с поддержкой HTML5 и т. Д.

Как ты это делаешь

Вернувшись к JavaFX 1.3, вы можете встроить Swing в JavaFX, но не наоборот, по крайней мере, официально. Я реализовал компонент Swing, который позволил вам встраивать содержимое JavaFX в Swing (называемое JXScene) и сделал его общедоступным в проекте jfxtras. Это был единственный способ встроить сцену JavaFX в приложение Swing.

Теперь Oracle с JavaFX 2.X сделал официальный способ встраивания JavaFX в Swing, который имеет больше смысла, но, к сожалению, не является способом встраивания Swing в JavaFX, я думаю, этого будет достаточно в большинстве случаев. Однако с выходом JavaFX 8 у вас также будет возможность встраивать компонент Swing в приложение JavaFX с помощью Swing Node.

ARQUITECTURE

По сути, когда вы встраиваете JavaFX в Swing, вы получаете 2 работающих потока пользовательского интерфейса: поток Swing EDT и поток пользователя JavaFX.

Существует вероятность того, что в будущем будет только один поток для обоих, как в случае с SWT, что заставит Swing работать в пользовательском потоке JavaFX, но сейчас нам придется управлять нашим способом с двумя потоками.

Два потока, выполняющиеся одновременно в пользовательском интерфейсе, — вот что усложняет ситуацию и делает интеграцию JavaFX не так легко, как вы могли бы ожидать, если только вы не создаете какое-то тривиальное небольшое приложение, но я полагаю, что это не сценарий для большей части реального мира случаи применения. Если вы делаете небольшое приложение, то можете сделать все это в JavaFX.

КОДИРОВАНИЕ

JavaFX предоставляет вам JFXPanel, которая представляет собой панель Swing, на которой размещена сцена JavaFX. Вы устанавливаете сцену на JFXPanel и добавляете панель везде, где вы можете добавить компонент Swing.

Для доступа к данным JavaFX вы должны обернуть ваш код в объект Runnable и вызвать метод Platform.runLater :

01
02
03
04
05
06
07
08
09
10
jbutton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                fxlabel.setText("Swing button clicked!");
            }
        });
    }
});

На другой стороне находятся данные Swing. Эти данные должны быть доступны только EDT. Чтобы убедиться, что ваш код выполняется в EDT, оберните его в объект Runnable и вызовите SwingUtilities.invokeLater :

1
2
3
4
5
6
SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        //Code to change Swing data.
    }
});

подсказки

  1. JavaFX уже генерирует исключения, когда вы обращаетесь к ресурсу JavaFX за пределами пользовательского потока JavaFX, но имейте в виду, что это не всегда происходит. Чтобы минимизировать затраты производительности, проверяются не все ситуации.
  2. Если вы используете Substance (по моему мнению, без сомнения, лучше всего выглядящий свободно и непринужденно), сторонняя библиотека, кроме исключения, будет также выброшена при каждом обращении к ресурсу Swing вне EDT. Настройка Substance в качестве внешнего вида Swing может быть хорошим решением для уменьшения количества ошибок параллелизма на стороне Swing, которые вы могли бы совершить.
  3. Будьте очень осторожны при совместном использовании ресурсов между двумя потоками пользовательского интерфейса, старайтесь избегать этого в максимально возможной степени. Лучший способ решить проблемы с многопоточностью — это избегать их, и такие проблемы являются одними из самых трудных для решения в программной инженерии. Существует причина, по которой Swing начинал как многопоточный инструментарий и заканчивал переходом на однопоточный.
  4. Иногда вам может потребоваться проверить, находитесь ли вы в пользовательском потоке JavaFX через Platform.isFxApplicationThread() и только runLater(...) вызываете Platform.runLater(…) , потому что если вы находитесь в пользовательском runLater(...) JavaFX и вызываете runLater(...) выполнение кода, который находится внутри, все еще будет отложено до более позднего времени, и это может быть не тем, что вы хотите.
  5. Существует множество элементов управления JavaFX, которые охватывают их аналог Swing, однако они отличаются и имеют разные функции, к которым вы должны адаптироваться. Есть также некоторые элементы управления, такие как JFormattedTextField, которые еще не существуют. В заключение, JavaFX отличается от Swing. Имеет разные элементы управления и другую архитектуру и API, к которым вы должны адаптироваться.

Другие ссылки, чтобы проверить:

Ссылка: Интеграция JavaFX и Swing (пересмотренная) от нашего партнера JCG Педро Дуке Виейры в блоге Pixel Duke .