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

时间:2015-06-11 07:54:10

标签: java swing windows-8.1 scaling screen-resolution

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

这就是我的意思:

scaling issue

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

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

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

调用对话框
JOptionPane.showMessageDialog(frame, msg, "Information", JOptionPane.INFORMATION_MESSAGE);
顺便说一下。

3 个答案:

答案 0 :(得分:3)

这是一个讨厌的,黑客的,快速修复的解决方案,它可以通过将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
}

答案 1 :(得分:2)

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

一个例外是System 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

答案 2 :(得分:1)

根据罗莎的回答,我创建了一个更简洁,更简洁的变体:

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);
}  

P.S。:由于声誉系统,我无法对罗莎的帖子发表评论。

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