Почему вы можете захотеть сделать это в своем приложении
Возможно, вы захотите переписать свое приложение Swing и изменить его на использование JavaFX. Самый простой способ — сделать это постепенно, меняя каждый компонент за раз. Для этого необходимо интегрировать каждый из недавно измененных компонентов JavaFX с остальным приложением Swing.
Я резюмирую, почему вы можете начать переписывать свое приложение с Swing на JavaFX:
- Это будущее
Swing в значительной степени мертв в том смысле, что он не получит дальнейшего развития. JavaFX — это новый инструментарий пользовательского интерфейса для Java, он лучше подготовлен к будущему с такими вещами, как сенсорная поддержка, 3D, встроенная поддержка анимации, воспроизведение видео и аудио и т. Д.
- Вероятная будущая поддержка мобильных устройств: Android, IOS…
Из того, что я видел, я думаю, что это в значительной степени гарантия того, что поддержка Android, IOS и т. Д. Будет доступна, у Oracle уже есть рабочие прототипы этого, которые они показывают на публичных конференциях, единственный вопрос — когда. Я думаю, что это не займет много времени, возможно, мы увидим больше об этом в следующем JavaOne, который скоро появится.
- Это твердое тело
JavaFX — это хорошо разработанный инструментарий с быстро растущим темпом, блестящим будущим и набором хороших бесплатных инструментов для пользовательского интерфейса. Кроме того, в отличие от прошлого, Oracle придает большое значение обратной связи с разработчиками, изменяя и адаптируя свои API для достижения своих целей.
- Это довольно
В отличие от Swing, не считая сторонних библиотек, что само по себе было некрасиво, JavaFX выглядит хорошо с самого начала. Учитывая, что в настоящее время пользователи ожидают хорошо выглядящих хорошо разработанных приложений, это довольно хороший момент.
- Приятные дополнения
Некоторые приятные дополнения, такие как API диаграмм, встроенный браузер с поддержкой HTML5 и т. Д.
Как ты это делаешь
Вернувшись к JavaFX 1.3, вы можете встроить Swing в JavaFX, но не наоборот, по крайней мере, официально. Я реализовал компонент Swing, который позволил вам встраивать содержимое JavaFX в Swing (называемое JXScene) и сделал его общедоступным в проекте jfxtras. Это был единственный способ встроить сцену JavaFX в приложение Swing.
Теперь Oracle с JavaFX 2.X сделал официальный способ встраивания JavaFX в Swing, который имеет больше смысла, но, к сожалению, не является способом встраивания Swing в JavaFX, однако, я думаю, этого будет достаточно в большинстве случаев.
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. } }); |
подсказки
- JavaFX уже генерирует исключения, когда вы обращаетесь к ресурсу JavaFX за пределами пользовательского потока JavaFX, но имейте в виду, что это не всегда происходит. Чтобы минимизировать затраты производительности, проверяются не все ситуации.
- Если вы используете стороннюю библиотеку Substance, то исключение также будет генерироваться при каждом доступе к ресурсу Swing вне EDT. Настройка Substance в качестве внешнего вида Swing может быть хорошим решением для уменьшения количества ошибок параллелизма на стороне Swing, которые вы могли бы совершить.
- Будьте очень осторожны при совместном использовании ресурсов между двумя потоками пользовательского интерфейса, старайтесь избегать этого в максимально возможной степени. Лучший способ решить проблемы с многопоточностью — это избегать их, и такие проблемы являются одними из самых трудных для решения в программной инженерии. Существует причина, по которой Swing начинал как многопоточный инструментарий и заканчивал переходом на однопоточный.
- Иногда вам может потребоваться проверить, находитесь ли вы в пользовательском потоке JavaFX через
Platform.isFxApplicationThread()
и толькоrunLater(...)
вызываетеPlatform.runLater(…)
, потому что если вы находитесь в пользовательскомrunLater(...)
JavaFX и вызываетеrunLater(...)
выполнение кода, который находится внутри, все еще будет отложено до более позднего времени, и это может быть не тем, что вы хотите.
Другие ссылки, чтобы проверить:
- Руководство по Oracle: http://docs.oracle.com/javafx/2/swing/jfxpub-swing.htm
Ссылка: Интеграция JavaFX и Swing от нашего партнера JCG Педро Дуке Виейры в блоге Pixel Duke .