高分辨率(MS Surface)上的错误Swing UI缩放

我目前正在开发一个涉及Swing GUI的小型Java应用程序。 在我的开发PC上,一切看起来都不错,但是当我在MS Surface上运行它时,某些图标对于组件来说似乎太大了(或者组件对于图标而言太小)。

这就是我的意思:

扩展问题

谷歌的研究让我得出结论,这是由于Surface的高分辨率和Win8的缩放,让一些项目显得更大。 所以我将缩放重置为100%,它实际上修复了不良缩放。

不幸的是,这并没有真正解决我的问题。 没有变焦,一切都太小了,所以我宁愿不禁用它。 但有没有聪明的方法来解决这个问题? 我可以只“缩放”我的程序或Java的图标吗? 理想情况下,我甚至想要升级整个画面,因为一切都很小。

编辑:显然,我也试过调整实际的JFrame大小,但它对对话框大小没有影响。 我正在通过调用对话框

JOptionPane.showMessageDialog(frame, msg, "Information", JOptionPane.INFORMATION_MESSAGE); 

顺便说说。

这是一个讨厌的,hacky,快速解决方案,通过将Swing自己的图标调整为80%来阻止令人讨厌的裁剪。

main ,添加:

 String[] iconOpts = {"OptionPane.errorIcon", "OptionPane.informationIcon", "OptionPane.warningIcon", "OptionPane.questionIcon"}; for (String key : iconOpts) { ImageIcon icon = (ImageIcon) UIManager.get(key); Image img = icon.getImage(); BufferedImage bi = new BufferedImage( img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); java.awt.Graphics g = bi.createGraphics(); g.drawImage(img, 0, 0, (int) (img.getWidth(null) * 0.8), (int) (img.getHeight(null) * 0.8), null); ImageIcon newIcon = new ImageIcon(bi); UIManager.put(key, newIcon); } 

您可能需要先检查是否确实需要这样做 – Windows 8/10默认为125%,但有些人会将其切换回100%。 我没有找到一种优雅的方法来做到这一点,但这些方面的内容会给你一个想法:

 java.awt.Font font = (java.awt.Font) UIManager.get("Label.font"); if (font.getSize() != 11) { //resize icons in here } 

大多数Swing外观和感觉根本不支持高DPI,甚至不支持Nimbus,即使它应该是可扩展的。 我发现一些老博客post说Nimbus可能最终提供高DPI缩放,但显然从未发生过。

系统LAF是一个例外,但在所有DPI设置下,其默认字体比实际系统字体大小小约10%。 此外,必须按照此处所述明确选择系统: http : //docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

您也可以在Swing中设置单个缩放因子。 具体的LAF必须提供处理扩展的代码。 所以你能做的最好就是选择系统并希望它足够好。

但是,JavaFX可以在我的系统上正确地自动扩展到150%。 如果可能的话,我建议您使用JavaFX来构建GUI。

编辑:我制作了一些小型测试程序,并对各种GUI框架,Swing主题和DPI设置进行了比较截图。 这可能是阅读这个问题的人的信息: http : //kynosarges.org/GuiDpiScaling.html

基于罗莎的答案,我创建了一个更简短,更简洁的变体:

 String[] iconOpts = {"OptionPane.errorIcon", "OptionPane.informationIcon", "OptionPane.warningIcon", "OptionPane.questionIcon"}; for (String key : iconOpts) { ImageIcon icon = (ImageIcon) UIManager.get(key); Image img = icon.getImage(); ImageIcon newIcon = new ImageIcon(img.getScaledInstance(img.getWidth(null), img.getHeight(null), 0)); UIManager.put(key, newIcon); } 

PS:由于声誉系统,我无法对罗莎的post发表评论。

编辑:在我看来,Java 10已经包含了针对highdpi扩展的修复程序。 因此,在使用此处的任何解决方案之前,请先检查java版本。