在 JavaFX 中获取监视器刷新率
Get Monitor Refresh Rate in JavaFX
通过AWT/Swing获取显示器的刷新率:
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDisplayMode()
.getRefreshRate()
问题:JavaFX获取刷新率有没有类似的method/procedure?如果有的话,怎么做?
在 JavaFX
中没有等效的 public API
这是 DisplayMode.getRefreshRate()
您当前使用的 awt API 的 javadoc:
Returns the refresh rate of the display, in hertz.
没有等效的 public JavaFX API。
如果 public api 存在于 JavaFX 中,它可能可以通过 Screen class 访问,但那里没有定义此类功能的访问器。
有一个未记录、不受支持的私有 API,它似乎提供类似的功能:
com.sun.javafx.tk.Toolkit.getToolkit().getRefreshRate()
JavaFX 脉冲处理
有关 JavaFX 工作原理的相关信息可以在 JavaFX 体系结构描述的 pulse 文档中找到。
A pulse is an event that indicates to the JavaFX scene graph that it is time to synchronize the state of the elements on the scene graph with Prism. A pulse is throttled at 60 frames per second (fps) maximum and is fired whenever animations are running on the scene graph. Even when animation is not running, a pulse is scheduled when something in the scene graph is changed. For example, if a position of a button is changed, a pulse is scheduled.
When a pulse is fired, the state of the elements on the scene graph is synchronized down to the rendering layer.
屏幕硬件刷新率不同于JavaFX内部脉冲处理率。虽然我猜想这些可以在内部实现中同步(在某些情况下可能会发生)在技术上是可能的,但 public 文档中没有任何内容提到是否实际发生了。
关于自适应刷新技术的说明
另请注意,随着 gsync and free sync 等技术的出现,刷新率可以适应内容。
Vertical synchronization is an option in most systems in which the video card is prevented from doing anything visible to the display memory until after the monitor finishes its current refresh cycle . . . technologies like FreeSync and G-Sync reverse the concept and adapts the display's refresh rate to the content coming from the computer. Such technologies require specific support from both the video adapter and the display.
此类技术充其量使依赖显示器中的硬件刷新率的概念变得有点模糊。
常见问题解答
您声明查询显示刷新率的目的是:
Like drawing anything as fast, as long as it's still achievable by the monitor...
无论显示器规格如何,默认情况下 JavaFX 有意将帧速率限制在 60fps。
可以使用未记录的系统属性覆盖此上限,如下所述:
- How to ignore the 60fps limit in javafx?
您可以使用未记录的功能删除 JavaFX 中的帧速率上限,然后依靠底层视频卡驱动程序和硬件以屏幕的底层硬件和软件功能内可用的最大速率呈现。
这是处理 openjfx source.
中的代码
/*
* Called to set the value of PULSE_DURATION or PULSE_DURATION_NS based on
* the refresh rate of the primary screen (unless overridden by the
* FRAMERATE_PROP Setting). If the refresh rate can not be determined the
* default of 60hz is used.
*
* @param precision - precision in (1000 for ms or 1000000000 for ns)
*
* @return pulse duration value, either in ms or ns depending on the
* parameter.
*/
protected int getPulseDuration(int precision) {
int retVal = precision / 60;
// Allow Setting to override monitor refresh
if (Settings.get(FRAMERATE_PROP) != null) {
int overrideHz = Settings.getInt(FRAMERATE_PROP, 60);
if (overrideHz > 0) {
retVal = precision / overrideHz;
}
} else if (Settings.get(PULSE_PROP) != null) {
int overrideHz = Settings.getInt(PULSE_PROP, 60);
if (overrideHz > 0) {
retVal = precision / overrideHz;
}
} else {
// If not explicitly set in Settings, try to set based on
// refresh rate of display
int rate = Toolkit.getToolkit().getRefreshRate();
if (rate > 0) {
retVal = precision / rate;
}
// if unknown, use default
}
return retVal;
}
在源代码中,帧率由未记录的 属性 javafx.animation.framerate
控制,对应于上述源代码中的设置 FRAMERATE_PROP
和 javafx.animation.pulse
对应于设置 PULSE_PROP
.
内部工具包 class 提供后备 API 以使用显示器的刷新率。
因此,也许您可以通过将系统 属性 javafx.animation.framerate
设置为 com.sun.javafx.tk.Toolkit.getToolkit().getRefreshRate()
的值或同时设置 javafx.animation.framerate
和 javafx.animation.pulse
为空。我没有试过这个,所以我不知道。需要注意确保您设置的值得到正确维护,并且不会被默认值覆盖。
您需要注意,如果您这样做,您正在使用未记录的 APIs,因此这将需要打开适当的模块导出,以便可以访问 APIs,并且在平台的未来版本中可能会被删除或变得不兼容,恕不另行通知(尽管这些设置目前多年来一直未更改)。
So I have been reading the link you provided, and to me, it seems JavaFX is simply stuck at 60fps because it prefers to?
默认情况下,是的,这是一个权衡。
对于通常使用 JavaFX 开发的应用程序类型,无论设备的底层硬件功能如何,脉冲渲染机制内的 60fps 刷新最大值通常就足够了。对于大多数 JavaFX 应用程序而言,将速率上限提高到该水平以上通常不是一个好的权衡,因为这意味着使用更高的资源(CPU 和视频处理能力和功耗),以获得刷新更新的收益,这对大多数人来说通常是检测不到的用户,通常不受底层硬件支持。
就是说,如果您想覆盖此默认限制,如上所述,有未记录的方法。
Why not use the same method?
在这种情况下,使用 AWT 方法可能是一个合理的选择。
硬件刷新不会根据所选的 UI 工具包而改变。
目前(JavaFX 17),JavaFX 系统依赖于 java.awt
包(javafx.base
模块需要 java.desktop
模块,其中包含所有 awt classes ).因此,如果 JavaFX 可用,那么 java.awt.DisplayMode
class.
因此,如果目标是确定硬件刷新率,您可以使用现有的 awt API。
The refresh rate won't change when using Swing or JavaFX right?
硬件刷新率不会根据使用的 UI 工具包而改变。
JavaFX 中用于更新场景图渲染的场景图脉冲率的定义与刷新率有些相关,但它只是一个 JavaFX 概念,因为 Swing 在其渲染阶段不使用场景图。
通过AWT/Swing获取显示器的刷新率:
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDisplayMode()
.getRefreshRate()
问题:JavaFX获取刷新率有没有类似的method/procedure?如果有的话,怎么做?
在 JavaFX
中没有等效的 public API这是 DisplayMode.getRefreshRate()
您当前使用的 awt API 的 javadoc:
Returns the refresh rate of the display, in hertz.
没有等效的 public JavaFX API。
如果 public api 存在于 JavaFX 中,它可能可以通过 Screen class 访问,但那里没有定义此类功能的访问器。
有一个未记录、不受支持的私有 API,它似乎提供类似的功能:
com.sun.javafx.tk.Toolkit.getToolkit().getRefreshRate()
JavaFX 脉冲处理
有关 JavaFX 工作原理的相关信息可以在 JavaFX 体系结构描述的 pulse 文档中找到。
A pulse is an event that indicates to the JavaFX scene graph that it is time to synchronize the state of the elements on the scene graph with Prism. A pulse is throttled at 60 frames per second (fps) maximum and is fired whenever animations are running on the scene graph. Even when animation is not running, a pulse is scheduled when something in the scene graph is changed. For example, if a position of a button is changed, a pulse is scheduled.
When a pulse is fired, the state of the elements on the scene graph is synchronized down to the rendering layer.
屏幕硬件刷新率不同于JavaFX内部脉冲处理率。虽然我猜想这些可以在内部实现中同步(在某些情况下可能会发生)在技术上是可能的,但 public 文档中没有任何内容提到是否实际发生了。
关于自适应刷新技术的说明
另请注意,随着 gsync and free sync 等技术的出现,刷新率可以适应内容。
Vertical synchronization is an option in most systems in which the video card is prevented from doing anything visible to the display memory until after the monitor finishes its current refresh cycle . . . technologies like FreeSync and G-Sync reverse the concept and adapts the display's refresh rate to the content coming from the computer. Such technologies require specific support from both the video adapter and the display.
此类技术充其量使依赖显示器中的硬件刷新率的概念变得有点模糊。
常见问题解答
您声明查询显示刷新率的目的是:
Like drawing anything as fast, as long as it's still achievable by the monitor...
无论显示器规格如何,默认情况下 JavaFX 有意将帧速率限制在 60fps。
可以使用未记录的系统属性覆盖此上限,如下所述:
- How to ignore the 60fps limit in javafx?
您可以使用未记录的功能删除 JavaFX 中的帧速率上限,然后依靠底层视频卡驱动程序和硬件以屏幕的底层硬件和软件功能内可用的最大速率呈现。
这是处理 openjfx source.
中的代码/*
* Called to set the value of PULSE_DURATION or PULSE_DURATION_NS based on
* the refresh rate of the primary screen (unless overridden by the
* FRAMERATE_PROP Setting). If the refresh rate can not be determined the
* default of 60hz is used.
*
* @param precision - precision in (1000 for ms or 1000000000 for ns)
*
* @return pulse duration value, either in ms or ns depending on the
* parameter.
*/
protected int getPulseDuration(int precision) {
int retVal = precision / 60;
// Allow Setting to override monitor refresh
if (Settings.get(FRAMERATE_PROP) != null) {
int overrideHz = Settings.getInt(FRAMERATE_PROP, 60);
if (overrideHz > 0) {
retVal = precision / overrideHz;
}
} else if (Settings.get(PULSE_PROP) != null) {
int overrideHz = Settings.getInt(PULSE_PROP, 60);
if (overrideHz > 0) {
retVal = precision / overrideHz;
}
} else {
// If not explicitly set in Settings, try to set based on
// refresh rate of display
int rate = Toolkit.getToolkit().getRefreshRate();
if (rate > 0) {
retVal = precision / rate;
}
// if unknown, use default
}
return retVal;
}
在源代码中,帧率由未记录的 属性 javafx.animation.framerate
控制,对应于上述源代码中的设置 FRAMERATE_PROP
和 javafx.animation.pulse
对应于设置 PULSE_PROP
.
内部工具包 class 提供后备 API 以使用显示器的刷新率。
因此,也许您可以通过将系统 属性 javafx.animation.framerate
设置为 com.sun.javafx.tk.Toolkit.getToolkit().getRefreshRate()
的值或同时设置 javafx.animation.framerate
和 javafx.animation.pulse
为空。我没有试过这个,所以我不知道。需要注意确保您设置的值得到正确维护,并且不会被默认值覆盖。
您需要注意,如果您这样做,您正在使用未记录的 APIs,因此这将需要打开适当的模块导出,以便可以访问 APIs,并且在平台的未来版本中可能会被删除或变得不兼容,恕不另行通知(尽管这些设置目前多年来一直未更改)。
So I have been reading the link you provided, and to me, it seems JavaFX is simply stuck at 60fps because it prefers to?
默认情况下,是的,这是一个权衡。
对于通常使用 JavaFX 开发的应用程序类型,无论设备的底层硬件功能如何,脉冲渲染机制内的 60fps 刷新最大值通常就足够了。对于大多数 JavaFX 应用程序而言,将速率上限提高到该水平以上通常不是一个好的权衡,因为这意味着使用更高的资源(CPU 和视频处理能力和功耗),以获得刷新更新的收益,这对大多数人来说通常是检测不到的用户,通常不受底层硬件支持。
就是说,如果您想覆盖此默认限制,如上所述,有未记录的方法。
Why not use the same method?
在这种情况下,使用 AWT 方法可能是一个合理的选择。
硬件刷新不会根据所选的 UI 工具包而改变。
目前(JavaFX 17),JavaFX 系统依赖于 java.awt
包(javafx.base
模块需要 java.desktop
模块,其中包含所有 awt classes ).因此,如果 JavaFX 可用,那么 java.awt.DisplayMode
class.
因此,如果目标是确定硬件刷新率,您可以使用现有的 awt API。
The refresh rate won't change when using Swing or JavaFX right?
硬件刷新率不会根据使用的 UI 工具包而改变。
JavaFX 中用于更新场景图渲染的场景图脉冲率的定义与刷新率有些相关,但它只是一个 JavaFX 概念,因为 Swing 在其渲染阶段不使用场景图。