JFXPanel setScene 冻结与 Java 11

Kri*_*nom 3 java windows openjfx 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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

此代码在 JDK-8 中运行良好,但不适用于 java-11.0.1。

我对这个问题一无所知,有点卡在 Java11 JavaFX 问题上。代码有问题吗?或任何报告的 javafx for java11 问题

Sla*_*law 5

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

有一些相关的限制JFXPanel。作为Swing组件,它应该只从事件调度线程访问,除了setScene(javafx.scene.Scene)方法,该方法既可以在事件调度线程或JavaFX应用程序线程调用。

setScene在一个Platform.runLater呼叫(或SwingUtilities.invokeLater)。

Platform.runLater(() -> {
    dummyPanel.setScene(dummyScene);
    System.out.println("Scene Created");
});
Run Code Online (Sandbox Code Playgroud)

请注意,使用您当前的代码,一旦main返回,JVM 将继续运行。创建 aJFXPanel初始化 JavaFX 运行时,该运行时在最后一个窗口关闭(仅当Platform.isImplicitExittrue)或被Platform.exit调用时才会退出。由于您的代码两者都没有,JavaFX 运行时将继续运行。


的文档JFXPanel还提供了一个如何使用它的示例(注意几乎所有事情都发生在Event Dispatch ThreadJavaFX Application Thread 上):

这是一个典型的模式如何JFXPanel使用:

 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();
             }
         });
     }
 }
Run Code Online (Sandbox Code Playgroud)

  • 我怀疑在为 Java 9 模块化 JDK 和 JavaFX 库时发生了一些不错的变化。随着 JavaFX 11 与 JDK 的分离,他们也一直在移除对内部 Swing 代码的依赖——而是更喜欢公共 API。因此,虽然我不知道细节,但如果实现至少在某种程度上没有改变,我会感到惊讶。此外,`JFXPanel` 的文档在 JavaFX 8 中是相同的,这意味着您可能只是走运(或无意中依赖于某些实现细节)。 (2认同)