JFXPanel setScene 冻结 java 11

JFXPanel setScene freezing with java 11

我想将 openjfx 集成到我的 Java 11 代码中。在 Windows 10 上使用 IntelliJ IDEA 2018.2.6,我创建了一个测试项目并尝试了以下代码

import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.TabPane;

public class Java11FXTestApplication {



    public static void main(String[] args) {
        JFXPanel dummyPanel;
        TabPane dummyTabPane;
        Scene dummyScene;
        System.out.println("Creating JFX Panel");
        dummyPanel = new JFXPanel();
        System.out.println("Creating  TabPane");
        dummyTabPane = new TabPane();
        System.out.println("Creating  Scene");
        dummyScene = new Scene(dummyTabPane);
        System.out.println("Setting  Scene");
        dummyPanel.setScene(dummyScene); //Freezing here
        System.out.println("Scene Created");
    }
}

此代码在 setScene() 方法调用中冻结。 我尝试调试它,发现它的代码在 JFXPanel.setScene 方法的 secondaryLoop.enter() 调用中无限期等待。知道为什么吗?

This code works fine in JDK-8 but not working with java-11.0.1.

我对这个问题毫无进展,有点卡在 Java11 JavaFX 问题上。代码有问题吗?或 java11

的任何已报告的 javafx 问题

您正在主线程上设置 Scene。来自 JFXPanel 的文档(强调 我的):

There are some restrictions related to JFXPanel. As a Swing component, it should only be accessed from the event dispatch thread, except the setScene(javafx.scene.Scene) method, which can be called either on the event dispatch thread or on the JavaFX application thread.

Platform.runLater 调用(或 SwingUtilities.invokeLater)中包装 setScene

Platform.runLater(() -> {
    dummyPanel.setScene(dummyScene);
    System.out.println("Scene Created");
});

请注意,使用您当前的代码,一旦 main returns,JVM 将继续 运行。创建一个 JFXPanel 初始化 JavaFX 运行time,直到最后一个 window 关闭(仅当 Platform.isImplicitExittrue 时)或 Platform.exit 被调用。由于您的代码两者都没有,因此 JavaFX 运行time 将保持 运行ning.


JFXPanel 的文档还给出了一个示例,说明它的预期使用方式(注意几乎所有事情都发生在 事件调度线程 JavaFX 应用线程):

Here is a typical pattern how JFXPanel can used:

 public class Test {

     private static void initAndShowGUI() {
         // This method is invoked on Swing thread
         JFrame frame = new JFrame("FX");
         final JFXPanel fxPanel = new JFXPanel();
         frame.add(fxPanel);
         frame.setVisible(true);

         Platform.runLater(new Runnable() {
             @Override
             public void run() {
                 initFX(fxPanel);
             }
         });
     }

     private static void initFX(JFXPanel fxPanel) {
         // This method is invoked on JavaFX thread
         Scene scene = createScene();
         fxPanel.setScene(scene);
     }

     public static void main(String[] args) {
         SwingUtilities.invokeLater(new Runnable() {
             @Override
             public void run() {
                 initAndShowGUI();
             }
         });
     }
 }