High-Resolution Swing UI Scaling (MS Surface)

I am currently working on a small Java application that includes a Swing GUI. Everything looks fine on my development PC, but when I run it on my MS surface, some of the icons seem too big for the components (or too small for the component icons).

Here is what I mean:

scaling issue

A Google study led me to conclude that this is due to the high resolution of Surface and the scaling of Win8 so that some elements look a bit larger. So, I reset, which increased to 100%, and actually it fixed poor scaling.

Unfortunately, this does not really fix my problem. Everything is too small, without scaling, so I would not turn it off. But is there any smart way to solve this? Can I just โ€œrevealโ€ my program or Java icons? Ideally, I would even like the whole frame to be expanded, because everything is quite small.

Edit: Obviously, I also tried just resizing the actual JFrame, but it does not affect the size of the dialog box. I am causing a dialogue

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

by the way.

+6
source share
3 answers

Here's a nasty, hacked, quick fix that will stop nasty cropping by resizing your own Swing 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 check first if this is really necessary - for Windows 8/10, the default is 125%, but some people will return it 100%. I have not found an elegant way to do this, but something like that will give you an idea:

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

Most Swing Look and Feels do not support a high DPI level at all, even Nimbus, although it should be scalable. I found some old blog posts that said that Nimbus might eventually offer DPI scaling, but this did not seem to happen.

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

There is not a single scaling factor that you could set in Swing. A particular LAF should provide code for scaling processing. Therefore, best of all, you can choose System and hope for it quite well.

However, JavaFX does the right thing and automatically scales to 150% on my system. If at all possible, I suggest you use JavaFX to create a GUI.

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

+1
source

Based on rosa's answer, I created a shorter less verbose version:

 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: Due to the reputation system, I could not comment on the rosa post.

0
source

Source: https://habr.com/ru/post/988900/


All Articles