Я работаю над приложением Java, в котором я использую этап JavaFX со встроенными компонентами Swing. Шаг за шагом я буду менять эти компоненты Swing на компоненты JavaFX, но в данный момент мне нужно скомпилировать и запустить приложение в этих условиях.
Для этого я установил флаг javafx.embed.singleThread
в "true", чтобы избежать общей ошибки, возникающей при попытке использовать JavaFX и Swing в одном приложении. Делая это, когда я запускаю приложение из IDE (я использую IntelliJ), все работает нормально, но когда я генерирую артефакт для создания JAR приложения, запускаю приложение из командной строки (я использую Windows), это выдается ошибка:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalStateException: FX and Swing thread should be merged. Are you using Java 8 and the javafx.embed.singleThread flag?
at sample.Main.start(Main.java:41)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:186)
... 1 more Exception running application sample.Main
Я читал о слиянии потоков JavaFX и Swing, и везде, где я ищу, я вижу один и тот же ответ, чтобы установить javafx.embed.singleThread
в "true". Но в моем случае это не работает. Может быть, что-то, чего я не осознавал, и нужно, чтобы этот JAR-файл работал?
Это не первый раз, когда я создаю JAR-файлы, но это первый раз, когда я делаю это, используя приложение с обоими Компоненты JavaFX и Swing.
Я не могу загрузить весь проект, но в начале основного метода здесь выдается исключение:
if ( !EventQueue.isDispatchThread() ){
throw new IllegalStateException(
"FX and Swing thread should be merged. Are you using Java 8 and the javafx.embed.singleThread flag?");
}
Спасибо за предоставленную помощь или связанные ссылки .
ОБНОВЛЕНИЕ : Я пытался использовать флаг, предложенный @Slaw в его комментарии в командной строке при запуске приложения .jar, и он работает! Сейчас я пытаюсь установить этот флаг не в командной строке, а в коде. Здесь я показываю, как запускается мое приложение и как я расширяюсь из класса Application:
public class Main extends Application {
SwingMainMenuRoundedPanel buttonsPanel = new SwingMainMenuRoundedPanel();
public Main() throws IOException {
System.setProperty("javafx.embed.singleThread", "true");
}
@Override
public void start(Stage primaryStage) throws Exception {
//System.setProperty("javafx.embed.singleThread", "true");
if ( !EventQueue.isDispatchThread() ){
throw new IllegalStateException(
"FX and Swing thread should be merged. Are you using Java 8 and the javafx.embed.singleThread flag?");
}
//Add Swing view and interface components to the FX frame
SwingNode viewNode = addSwingNodeToFXFrame(primaryStage);
//----------------------------------------------
//Add FX view and interface components to the FX frame
//----------------------------------------------
// Auxiliary panel with provisional content
Accordion auxiliaryPanelFX = new Accordion();
// Do the lay-out using FX
HBox hbox = new HBox(viewNode, auxiliaryPanelFX);
HBox.setHgrow(viewNode, Priority.ALWAYS);
// Show the window
primaryStage.setScene(new Scene(hbox));
primaryStage.setFullScreen(true);
primaryStage.setTitle("FXApp");
primaryStage.setResizable(false);
primaryStage.show();
}
...
}
Я попытался установить флаг свойства System внутри конструктора, как вы можете видеть сейчас, а также в закомментированной строке в Метод start (), но он не работает, я думаю, из-за причины, которую @Slaw сказал в своем комментарии. Системное свойство не устанавливается до запуска потока JavaFX. Каким будет правильный способ установки свойства System по коду в моем случае?
Большое спасибо за ваши комментарии!