0

我的课程扩展了 JavaFX 阶段。在开发环境中,它永远不会加载和处理失败,但我的用户经常报告说有时它不能正确显示在 Windows 10 上看起来像这样

该类本身是一个相当标准的事情,我使用 Platform.runLater() 触发它,并且线程进程按预期进行。每个日志输出都被写出,可以按照程序与屏幕交互,或者关闭它,这不会触发任何错误或异常。

阶段构造函数非常基本:

  log.debug("Constructing the screen.");

  setTitle("Screen");
  setAlwaysOnTop(true);
  initStyle(StageStyle.UNDECORATED);

  try {
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(getClass().getResource("....fxml"));

        Pane panel = fxmlLoader.load();
        controller = fxmlLoader.getController();
        controller.postInit(currentIdle); // some elements processed

        Scene scene = new Scene(panel);
        setScene(scene);

        scene.setOnKeyPressed(controller::handleKeyEvent);
        setOnHiding((WindowEvent e) -> processor::leaveScreen);
        log.debug("Showing the screen.");
        show();
        log.debug("Screen shown.");

        requestFocus();
        log.debug("Finished constructing the screen.");

} catch (IOException e) {
    // ...doesn't go here
}

从日志来看,一切似乎都按预期工作,包括控件、键盘快捷键和 leaveScreen() 挂钩,并且没有抛出异常,除了用户有时看不到屏幕上的内容和控件。

我在看什么?这是我的代码问题还是 JavaFX 错误?用户笔记本电脑上的图形有问题吗?你能想出一种方法来防止或至少检测到这种状态并以某种方式强制刷新吗?

或者,在什么情况下,JavaFX 阶段可能会通过其 show() 方法而没有错误,但实际上并未显示其内容?

受影响的环境:最新的 JDK 14 GA、Corretto 11(自定义 jlink 创建的映像)和 JavaFX 11.0.2 或 14.0.1 的所有组合 - 没有区别。无论应用程序是否使用 jpackage 或 Advanced Installer 安装了 jlinked JRE,它也会发生。

4

2 回答 2

0

如果没有更多信息,很难提供帮助,但我过去不得不为 Windows 问题使用的两件事是

Thread.currentThread().setContextClassLoader(App.class.getClassLoader());

放置在start(Stage stage)方法的开头,App显然替换为扩展类的名称Application

我使用的另一个“修复”是

System.setProperty("glass.accessible.force", "false");

作为单击失焦节点问题的解决方法

于 2020-04-24T10:17:38.260 回答
0

热烈感谢,伙计们,你们光荣的尝试提供帮助。九个月后现在有点冷,但我相信它应该结束,以防以后有人偶然发现这个问题。我的结论:

  1. 该问题不是由我的应用程序引起的,并且
  2. 我找到了解决方法。

我们逐渐自信地将问题与硬件隔离开来,也就是说,我们注意到如果涉及插入/拔出显示外围设备和扩展坞,它会更频繁地发生。有时也会因睡眠/电池电量不足而触发。

这让我们相信问题出在 Prism 的硬件加速和显卡之间。最后,我们设法通过将应用程序的 GraphicsPipeline从更改为com.sun.prism.d3d.D3DPipeline来避免这种渲染冻结com.sun.prism.sw.SWPipeline。对我们来说这不是问题,因为应用程序不会渲染复杂的 3D 图形,切换到软件渲染后问题就消失了。

这可以通过-Dprism.order=sw在启动时设置 JVM 参数来实现。您可以通过记录您的com.sun.prism.GraphicsPipeline.getPipeline().getClass().getName().

于 2021-01-29T17:09:52.477 回答