JavaFX 阶段 *有时* 在 Win10 上显示为空白

JavaFX stage *sometimes* appears blank on Win10

我的 class 扩展了一个 JavaFX 舞台。在开发环境中,它永远不会加载和处理失败,但我的用户经常报告说有时它无法正确显示 which looks like this on Windows 10.

class 本身是一个相当标准的事件,我用 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,它也会发生。

在没有更多信息的情况下很难提供帮助,但我在过去 windows 问题中不得不使用的两件事是

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

放置在 start(Stage stage) 方法的开头,其中 App 显然已替换为扩展 Application

的 class 的名称

我用过的另一个'fix'是

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

作为点击焦点不对的节点问题的变通方法

热烈感谢伙计们,感谢你们的光荣尝试。九个月后现在有点冷,但我相信它值得关闭,以防万一以后有人偶然发现这个问题。我的结论:

  1. 问题不是我的应用引起的,
  2. 我找到了解决方法。

我们逐渐设法自信地将问题隔离到硬件上,即我们注意到如果涉及 plugging/unplugging 显示外围设备和扩展坞,它会更频繁地发生。它有时也会因奇怪的睡眠/运行 电池没电而触发。

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

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

来确认正在使用的管道