【问题标题】:JavaFx/ Swing window does not open after update to Java 1.8u40JavaFx/Swing 窗口在更新到 Java 1.8u40 后无法打开
【发布时间】:2015-05-29 15:19:31
【问题描述】:

我们有一个主要在java 1.7 开发并在1.8 测试的javafx 应用程序。在java 1.8u35 之前它运行良好。现在我们发现,JavaFx 窗口在升级后不会在1.8u40 中打开。更糟糕的是,模态窗口阻止了整个选项卡/浏览器的使用。因此用户只需使用任务管理器关闭浏览器即可。

我们使用javafx.embed.swing.JFXPanel 将 jfx-code 嵌入到 swing 遗留代码中。

我完全不知道可能是什么问题,因为客户端的 java 控制台中没有显示错误。

更新:

我查看了java1.8 here 的已知问题列表。我唯一可能会链接到我们的问题的是这个错误:

BUG-RT-32597:SwingNode 类不支持高 DPI 显示。

所以我尝试降低屏幕分辨率(1280x1024 到 800x600)但没有成功。

以前有没有人遇到过类似的问题并且知道有什么帮助?

更新:

我试图更好地找出问题所在,但运气不佳。 为了让它更明显,这基本上是窗口加载时发生的事情:

public static void initWindow(JDialog dialog){

    final JFXPanel jfx = new JFXPanel();
    Platform.runLater(new Runnable() {
        public void run() {
            System.out.println("JFXPanel");
        }
    });

    Runnable r = new Runnable() {
        public void run() {

            AnchorPane root = new AnchorPane;
            //... do some content loading

            Scene scene = new Scene(root,width,height);
            System.out.println("test");
        }
    };

    dialog.add(jfx);
    System.out.println("added jfx panel.");

    dialog.pack();
    System.out.println("packed jfx panel.");

    dialog.setLocationRelativeTo(null);
    System.out.println("loaded.");

}

我以为执行会在某个地方停止,但它像往常一样贯穿整个函数。然而,窗口没有出现。

更新:

不完全正确,我发现的最后一条评论:

围绕上述函数,会发生以下情况:

initWindow(this); //this is extending java.swing.JDialog
System.out.println("this comment is printed to console");
super.setVisible(true); //this is not executed properly. if removed, browser will not be blocked, but window doesnt show up either
System.out.println("this comment is not printed to console";

所以,一般来说,JDialog 包含一个 JfxPanel。从 JDialog 类调用 setVisible() 方法时,应用程序被阻止但窗口不显示。实际上,在缩略图屏幕 (alt+tab) 中,它显示为应用程序内的容器。

删除 setVisible 调用时,浏览器不会被阻止,但窗口也不会显示。不幸的是,我没有找到 JDialog 类代码来查找,setVisible() 里面发生了什么。

任何想法,我们的设置或 setVisible 方法可能有什么问题?

【问题讨论】:

    标签: java swing javafx


    【解决方案1】:

    我们遇到了类似的问题。在比较 1.8.0_31 和 1.8.0_45 的 Java 源代码时,我们发现 1.8.0_45 引入的JFXPanel 源代码有一些变化,可能会导致以下情况出现问题:

    1. JFXPanel 初始化模态JDialog(在Swing 的EDT 上执行)
    2. 在 FX 任务中初始化并设置 JFXPanel 的 FX 场景(在 FX 线程上执行)
    3. 等待 FX 任务完成(等待 EDT)
    4. pack()show() JDialog(继续 EDT,阻止程序执行)
    5. 在用户关闭JDialog(在 EDT 上)后继续执行程序

    我们使用此工作流程来等待某些用户输入以新模式 JDialog 显示,然后在 EDT 上继续正常程序执行。

    在 1.8.0_31 中,JFXPanel 的首选大小似乎在 FX 线程中设置,这允许 JDialog.pack() 确定正确的边界。

    在 1.8.0_45 中,JFXPanel 的首选大小似乎不再在 FX 线程中设置,而是在执行所有未决 AWT 事件后在 EDT 中设置。因此,当执行 (4) 时,JDialog.pack() 不知道场景的首选大小。因此,对话框没有内容,或者如果未按照上述原始问题所述进行装饰,则不会显示。

    这里是重现不同行为的完整示例:

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
    
                // create JDialog on EDT
                final JDialog dialog = new JDialog((JDialog)null, "JDialog");
    
                // initialize FX platform and create JFXPanel
                final JFXPanel jfxPanel = new JFXPanel();
    
                // add resize listener for JFXPanel
                jfxPanel.addComponentListener(new ComponentAdapter() {
                    public void componentResized(ComponentEvent e) {
                        // not called in 1.8.0_45
                        System.out.println("JFXPanel.getSize(): "+jfxPanel.getSize());
                    }
                });
    
                // set FX Scene on JFXPanel and wait until finished
                runAndWait(new Runnable() {                
                    public void run() {
                        Text text = TextBuilder.create().text("JavaFx content").y(20).build();
                        Group root = new Group(text);
                        Scene scene = new Scene(root);
                        jfxPanel.setScene(scene);
                    }
                });
    
                // show undecorated modal JDialog with FX content
                System.out.println("JFXPanel.getPreferredSize(): "+jfxPanel.getPreferredSize());
                dialog.setUndecorated(true);
                dialog.add(jfxPanel);
                dialog.pack();
                dialog.setModal(true);
                System.out.println("JDialog.setVisible()");
                dialog.setVisible(true);
            }
        });
    }
    
    private static void runAndWait(Runnable r) {
        try {
            FutureTask<Object> task = new FutureTask<Object>(r, null);
            Platform.runLater(task);
            task.get();
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    

    运行此程序时,componentResized() 仅在 1.8.0_31 中调用,而在 1.8.0_45 中不调用。

    在 EDT 上保持同步程序工作流的同时,一个可能的解决方法是将 JDialog.pack() 替换为 JDialog.setSize(...),例如。 G。通过设置一个常量大小或使用可以使用root.getBoundsInLocal() 确定的 FX 场景的大小。

    【讨论】:

      【解决方案2】:

      我在使用 1.8.0_121 时遇到了 @Peter 所描述的相同行为。

      我能够使用窗口侦听器让 dialog.pack() 工作。

      dialog.addWindowListener( new WindowAdapter() {
          @Override
          public void windowOpened(WindowEvent e) {
              ((JDialog)e.getSource()).pack();
          }    
      }); 
      

      【讨论】:

        猜你喜欢
        • 2013-02-09
        • 1970-01-01
        • 2013-09-24
        • 2019-04-30
        • 2017-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-15
        相关资源
        最近更新 更多