JavaFX 中的像素、分辨率与缩放比

JavaFX 中的像素、分辨率与缩放比

  • 总结与补充

  JavaFX 中,一般需要对每个组件设置一个尺寸值,这个值实际上就是像素值(pixel,px)。像素值是什么呢?在 Windows 上,一般使用任意截图软件进行截图选定区域后,在左上角就会显示该区域的宽(width)和高(height),这个宽和高的单位就是像素。

  不过要注意的问题是,像素有相对值与绝对值之分。这个问题有点复杂,这里详细解释一下。

  • 绝对像素,指的是像素的最终实际值,也就是上面所说的截图软件中显示的值。关于这个值,在 Windows 中将使用两个参数来控制。一个是(显示)分辨率(resolution),另一个是缩放比例(scale)。任何 UI 在屏幕中显示时,最终使用的都是绝对像素值。


      关于分辨率和缩放比例,在 Windows 中可以自行设定,方法如下:

    JavaFX 中的像素、分辨率与缩放比_第1张图片

    JavaFX 中的像素、分辨率与缩放比_第2张图片


  • 相对像素,指的是像素的计算的基准值。上面所说的 JavaFX 组件的尺寸实际上是一个相对像素值


  绝对像素与相对像素之间有什么联系呢?绝对像素需要通过相对像素与缩放比例来算得。而显示器的分辨率将给出显示器的绝对像素值,也就是显示器右下角相对于左上角的绝对像素坐标。以笔者上面图片的中的为例,当分辨率为 1920 × 1080、缩放比例为 125% 时:

  • 显示器右下角的绝对像素坐标为:

    • width:1920

    • height:1080

  • 显示器右下角的相对像素坐标为:

    • width:1920 / 1.25 = 1536

    • height:1080 / 1.25 = 864

  • 屏幕中任意一点的绝对像素坐标为:

    (其中,(x, y) 为该点的相对对像素坐标。α 为屏幕的缩放比。)

    • width:x * α

    • height:y * α


    【提示】

    • 在 Java 中,有很多方式可以实现绝对像素与相对像素之间的转化。例如,在 JavaFX 中,可以使用如下方法分别获取宽和高的缩放比:

      double scaleX = Screen.getPrimary().getOutputScaleX();
      double scaleY = Screen.getPrimary().getOutputScaleY();
      
    • 还可以使用虚拟机参数 -Dprism.allowhidpi = XXX,来决定 JavaFX 是否采纳系统的缩放比。如果将此处的 XXX 设为 false,这相当于将系统的缩放比设为了 1。此虚拟机参数也可以在 Java 程序中指定,如下。不过,必须要在初始化 UI 程序之前设置才会生效。

      System.setProperty("prism.allowhidpi", "XXX"); // 其中,XXX 在实际的环境下应改为 true 或 false
      

      不过,程序不应该过分依赖此设置。由于此设置对整个 UI 界面都会起作用,所以不建议使用此设置来控制 UI 的行为。应该使用前面的方法获取缩放比来决定 UI 应该如何显示。

      很多应用都在设置提供了一种 适配系统缩放比例 的选项。这实际上就是决定系统的缩放比会不会生效。不生效指的是将缩放比视为 1。这个设置通常需要应用重启才会起作用。在 JavaFX 中,可以使用上述的方法来实现这个功能。


  绝对像素与相对像素以哪个为准比较好呢?不能一概而论。有些时候应该以绝对像素为准,有些时候应该以相对像素为准,有些时候无关紧要。由于 UI 在屏幕中显示时,最终使用的都是绝对像素值。所以这个问题就是考虑在编程中该以什么值来表示屏幕中的绝对像素。

  如果是以绝对像素为准(在代码、测量统计时的数据中直接使用绝对像素),就要求 UI 在各种环境下的界面尺寸都保持一致。有时候,光是考虑绝对像素也不能做到这一点,还要结合设备的型号和显示器尺寸作调节。因为显示屏的 DPI 可以通过调整分辨率来改变。但这会使用软件失去屏幕适配的能力,一般不会使用这种方法,因此 JavaFX 也没有采用。

  如果是以相对像素为准,就要求 UI 组件间的比例保持一致,而实际的大小无关紧要。

  如果希望 UI 组件可以自动调整大小与间距,则使用哪个无关紧要。

总结与补充

  • 在 JavaFX 中,传入组件的像素值一般是相对像素,而直接从屏幕中获取的像素是绝对像素。它们之间需要借助缩放比来进行转化。

  • 截图软件上显示的是绝对坐标。

  • 如果使用与屏幕坐标的相关 API 时,发现传入的坐标与实际生效的坐标差异很大,这说明此 API 可能使用的是相对坐标。请尝试将此坐标除以 屏幕缩放比 再进行传入。

你可能感兴趣的:(Java,概念辨析/科普,JavaFX,像素,分辨率,缩放比)