Bad Swing UI scaling on high resolution (MS Surface)

不想你离开。 提交于 2019-12-04 02:47:43

Here is a nasty, hacky, quick-fix solution which will stop the nasty cropping by resizing Swing's own icons to 80%.

In main, add this:

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

You might want to first check whether this is actually required - Windows 8/10 defaults to 125% but some people will switch it back to 100%. I haven't found an elegant way to do this, but something along these lines will give you an idea:

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

Most Swing Look & Feels don't support high DPI at all, not even Nimbus even though it's supposed to be scalable. I found some old blog posts saying that Nimbus might eventually offer high DPI scaling, but apparently that never happened.

The one exception is System LAF but its default font is ~10% smaller than the actual system font size, at all DPI settings. Moreover, System must be selected explicitly as described here: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

There's no single scaling factor that you could set in Swing, either. The specific LAF has to provide code to handle scaling. So the best you can do is select System and hope it's good enough.

However, JavaFX does correctly and automatically scale all the way up to 150% on my system. If at all possible, I suggest you use JavaFX to build your GUI.

edit: I made a couple small test programs and took comparison screenshots for various GUI frameworks, Swing themes, and DPI settings. This might be informative for people reading this question: http://kynosarges.org/GuiDpiScaling.html

Based on rosa's answer i created a shorter less verbose variant:

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.: Due to the reputation system i was not able to comment to rosa's post.

Edit: It seems to me like Java 10 has included a fix for highdpi scaling. So maybe check the java version first before using any of the solutions here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!