Java / Swing如何处理不同的屏幕DPI和密度设置?

大家好,我最近遇到的问题是,现在有些显示器有不同的DPI设置,有些显示器更密集,例如Apple的Retina显示器。

如何用Java补偿各种监视器上的不同DPI设置和密度? 是否可以在任何监视器上将控件缩放为相同的大小。 我知道在为Android编程时,所有测量都在“DP”中,您可以为三种不同的显示密度指定不同的图像。

有没有办法可以使用Java / Swing为不同的显示密度选择不同的图像,这样我的应用程序在高密度显示器上看起来并不模糊? 或者这不是那么重要或可能吗? 我知道Chrome目前没有考虑DPI,但是Internet Explorer和其他应用程序也是如此。

谢谢你的帮助,我是一名Java开发人员,我以前从未考虑过DPI,并且想知道我该怎么做:)

首先,请相信平台的Look&Feel设计师为文本和控件选择合理的默认大小。 然后,避免挫败这些默认值的诱惑。 以下是一些启发式方法:

  • 使用布局 ; 在考虑绝对定位时,请考虑自定义布局。

  • 尊重组件的首选大小 。

  • 避免使用不可resize的组件 。

  • 在动画中 ,将图形缩放到封闭Window的大小。

  • 根据需要使用仿真在一系列平台上进行测试。

首先,感谢trashgod为您提供的有用链接,他们非常有帮助。

下面我列出了一些关于如何处理我遇到的DPI变更问题的细节。

字体问题:

如果字体不适合组件,那么请查看下面的组件大小调整问题,因为组件通常不会调整内部的大小。 否则,在JLabel中,您可以应用HTML标记来自动换行文本(还有其他解决方案,但这对我有用)。

如果组件的文本自然是默认的字体,大小和样式(Tahoma 11 plain),那么一切都会自动完成。 知道user574171在他关于如何在Windows / Linux上设置Java Swing应用程序的DPI的答案中给出了与http://kynosarges.org/GuiDpiScaling.html链接中显示不同字体和布局管理器问题和优势的图片? 。 这里的问题是询问“Swing”问题,但是他的链接在将WPF,JavaFX和Swing布局与基本组件和不同字体进行比较时也很有用。 你可以看到那里的“Swing a”字体是最好的,那就是Tahoma 11 Plain。 但是它仅在组件自然是默认字体,大小和样式(Tahoma 11 Plain)时才有效。 这意味着粗体,下划线,大小调整,文本的不同字体将摒弃不同DPI的自动resize。

如果文本是默认字体(Tahoma)但是粗体,下划线或不同大小,则文本不会针对不同的DPI进行缩放。 要修复不同DPI的缩放比例,请选中标记为“从默认字体中导出字体”的复选框。 “相对”选项将采用默认的DPI缩放字体并应用您的相对更改,例如更大或更小,粗体和下划线。 还要知道,如果组件是JLabel,那么无论您如何格式化文本(行换行),DPI缩放都是使用HTML标签自动进行的。

如果组件自然不是默认的字体,样式和大小(Tahoma 11 plain)或者你想要一个不同的字体(即不是Tahoma),那么你需要将另一个组件中的更改与JLabel自然地作为默认关联。 因此,如果125 DPI将字体增加3,那么您将增加所需的字体。

组件大小调整问题:

所有组件都具有首选,最小和最大大小属性,但我发现它们在DPI更改方面效果不佳。 trashgod的答案中的“尊重组件的首选大小 ”子弹告诉您所有相关信息。 总结一下,让组件的默认大小自行处理,因为它会尝试调整内部的大小。

如果组件可以使用默认大小,则可以为您完成DPI处理。 正如trashgod所说:“首先,相信平台的外观和感觉设计师为文本和控件选择合理的默认大小。然后,避免挫败这些默认值的诱惑。” 同样,默认大小的组件通常会调整到内部的大小(或者可以resize)。 根据我自己的经验,当我设置可重复大小的组件时,我通过“Horizo​​ntal Resizable”或“Vertical Resizable”来完成它,因为我发现它可以很好地处理DPI更改以及窗口大小调整。

如果组件的默认大小不起作用,那么首先尝试查看我发现的一些特定问题。 或者,尝试根据正确缩放的组件中的更改来缩放组件。 IE,将您期望的缩放组件的比率应用于100%DPI以及更改为新DPI。 需要缩放到其他组件更改的组件的示例将是其文本由代码填充或者是图像的组件。

作为最后的手段,使用JScrollPane允许用户滚动以查看整个事物。 如果窗口/对话框相当大,那么JScrollPane是一个好主意,因为如果DPI对于用户的视力更高,则窗口通常比屏幕大。

注意:我发现在JPanel中封装组件组有助于更好地处理DPI更改。

JTextField大小问题:

如果您愿意,可以设置columns属性,而不是文本。 columns属性是您要显示的字母或数字的数量。 通常在允许用户输入数字时使用。 知道columns属性适用于多个平台。

JSpinner大小问题:

将模型设置为准确,有效和默认值。 因此,组件的自动resize是针对最大值完成的,并且对于DPI更改和其他平台非常有用。

表行高度问题:

表行高度不会随着DPI的增加而变化。 我遇到了这个问题,似乎是因为我试图与旧版本的Java兼容。 要修复由于DPI更改而导致的字体大小比率变化或JLabel高度比率变化。

使用JRE 9(或更高版本)。

这是因为Java运行时(旧版本)宣称自己是“DPI感知”,但并不真正支持它用于AWT和Swing。 Java应用程序的大小和渲染基于像素而不是正确缩放,这包括HiDPI显示。 无论如何,这最近已经解决了。 请参阅问题JEP 263:Windows和Linux上的HiDPI Graphics以及升级 。

因此,增加字体大小不起作用(因为它不会增加其余的东西); jvm参数-Dsun.java2d.dpiaware=false不起作用(因为它实际上不受支持); 并且清单文件+注册表编辑(对于Windows)只是不起作用。

然后,您需要在JRE 9上运行它,因为它确实支持此function。