Our SWT-based Java application automatically uses the default font-size of the operating system and that to derive other fonts. Hence, the texts of the GUI look fine on hi-res-screens (e.g. 2880 x 1620 with Windows 8 being configured as "Larger" in Control Panel > Appearance and Personalization > Display). Unfortunately, the images are not scaled, so, e.g., tool bar buttons appear too small.
On OS X the hi-res-screen handling seems easy: the virtual resolution is just half of the size, but how to do the scaling on Windows which seems to allow non-integer scaling factors? How to detect when to scale and when not?
Update
It looks like this SWT issue covers a similar problem.
Have a look at Neon (4.6) M6 - New and Noteworthy, the milestone release contains some automatic scaling for images (e.g. for toolbar).
SWT provides resolution-based auto-scaling
SWT now automatically scales images on high-DPI monitors on Windows
and Linux, similar to the Mac's Retina support on OS X. In the absence
of high-resolution images, SWT will auto-scale the available images to
ensure that SWT-based applications like Eclipse are scaled
proportionately to the resolution of the monitor.
This feature can be disabled on Windows and GTK by setting this VM
argument to false in eclipse.ini or on the command line after -vmargs:
-Dswt.enable.autoScale=false
Auto-scaling cannot be disabled on the Mac as it is provided by the
OS.
Caveats: We're aware that some scaled images look bad at scale factors
less than 200%. This will be improved in M7. Furthermore, we're
working on support for high-DPI images in Platform UI, so that plug-in
providers can add high-DPI icons without doing any code changes.
Or maybe this helps, in Eclipse Mars API for high resolution was added
New APIs have been added to provide support for rendering
high-resolution images on high-DPI monitors. Two constructors have
been added to the Image class. They accept image-provider callbacks
that allow clients to supply resolution-dependent versions of images:
public interface ImageDataProvider {
public ImageData getImageData (int zoom);
}
public interface ImageFileNameProvider {
public String getImagePath (int zoom);
}
Depending on the user's monitor configuration, SWT will request images
with the corresponding zoom level. Here's an example that displays 3
original images, followed by variants whose resolution changes
depending your monitor's resolution: Snippet367.java.
Note that this is just the first step to support high-resolution
images in SWT and Eclipse-based applications. Work is underway to
adopt the new APIs in the platform. Futhermore, more work in SWT is
required to properly support drawing into high-resolution images via
GC.
APIs for high-DPI monitor support
http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2FwhatsNew%2Fplatform_isv_whatsnew.html
Related
I have created a program using Java 8 that utilises a Swing GUI in the Eclipse IDE. To scale images and icons to appropriate sizes, it gets and uses the screen resolution. Upon compiling the program within Eclipse, the program displays perfectly fine, and everything seems to operate as it should. However, when I export the project as a "Runnable Jar", and run the program, the image scaling and the program look and feel are all off.
Upon further investigation, it appears that the runnable jar was returning a screen resolution that is exactly 2.5x less then that in eclipse (which is the actual resolution - 3840x2160 vs 1536x864). There is circumstantial evidence across the internet that Java 8 Look and Feels (or something of the sort) don't support HiDPI screen scaling. There are scattered solutions that claim to fix the problem, like updating to Java versions past 8, or by adding arguments to the jar compilation (whatever that means). This is already confusing to a Java novice, and it is only made more confusing by the program being displayed perfectly when run/compiled within the Eclipse IDE.
My question is whether anyone knows how to get a program compiled in Java using Swing to scale correctly on an HiDPI screen, and what the process is that I need to follow to compile a working program?
EDIT 1: Something interesting to note is that in my Windows settings, the "Scale and Layout", "Change the size of text, apps, and other items" is set to exactly 250%, meaning that this setting is obviously the cause of the scaling issues I am encountering. Does someone know how to bypass this setting from within the program, or why it works when I run it through Eclipse?
Java 8 does not support High DPI. On Windows, it runs in DPI unaware mode and relies on Windows to stretch the window bitmap to the scale set for the monitor in the settings. It means the UI of the application looks blurry when displayed on a High DPI monitor.
Later versions of Java, Java 11 and above, support per-monitor High DPI settings. The UI of your application is correctly scale up according to the settings, the text remains crisp. For the icons and images to remain crisp, you should use MultiResolutionImage or its basic implementation BaseMultiResolutionImage to provide higher resolution alternatives.
You should not base your images based on the screen resolution but rather on the scale set for a monitor. For example, a Full HD monitor 1920×1080 with 150% scale has the effective resolution 1280×720, it is the effective resolution that Java reports to you.
How can I make my Java Swing app GUI scale properly to users on high-DPI screens?
See the screenshot below. At the top you can see how tiny the app looks compared to Ubuntu's file explorer icons and gedit. In the bottom left you can see roughly what size the app should look like (and does look on regular DPI monitors). So I'm looking for a way to scale the GUI of the app properly when a high DPI monitor is in use. For example, gedit looks the same on both regular DPI and high DPI monitors. I want my app to behave like this.
Here is source code for the app: https://github.com/baobabKoodaa/baopass
This is an extremely common problem affecting many apps. Roughly half of the apps I run on Ubuntu are scaled properly without any actions from the user, the other half are not scaled and look really tiny. Note that I'm mainly looking for a solution that doesn't require actions from the user (although any help is appreciated at this point - I haven't found any ways to scale it at all).
According to this scaling should already work out of the box. It doesn't. I'm not sure if this is a bug or if there is some additional step I'm supposed to do besides running the app on Java 9?
You have to tell the drawing libraries to scale the app up.
GDK_SCALE=2 ./application
Will have the appropriate information set in the environment and the widgets will render scaled up such that each pixel effectively takes four pixels of footprint.
Note that the splash screen (if you use Java's splash screen support) isn't presented after the entire Swing libraries are loaded, so it won't scale regardless of the settings you attempt.
In some platforms, like the Linux distribution of Fedora, partial scaling is also possible, such that you can set GDK_SCALE=1.5. Just keep in mind that it's not universally available, and it is not settable to any scaling ratio you might want.
Finally, the older JVMs ignore this setting completely, so if you aren't launching with Java 9 or higher, odds are it won't work. And, of course, the way that things are tweaked for older JVMs and different operating systems tend to vary (if they work at all).
It looks like you're using Linux. You can use a command line switch
java -Dsun.java2d.uiScale=2 -jar some_application.jar
From https://wiki.archlinux.org/index.php/HiDPI#Java_applications
According to Eclipse Project Neon - New and Noteworthy, SWT supports auto-scaling for Hi-DPI monitors. Does SWT only support "auto-scaling", or does it provide additional features such as defining different images for various DPIs or zoom levels? If so, what are the classes I need to be looking into?
SWT's Image has a new constructor that accepts an ImageDataProvider in order to provide image data for different zoom levels. if the application is moved to a monitor with different DPI or the zoom level is changed, the provider will be asked to return an image for the new zoom level (e.g. 150 or 200).
For the sake of completeness, there is also an ImageFileNameProvider. It works similar to the ImageDataProvider but returns file names instead.
The JFace ImageDescriptor createFromFile and createFromURL methods look for additional image files with the name ending in #2x or #1.5x and will use these with an SWT image data provider when creating images.
We have a rather complex application that needs as much screen real-estate as it can get, naturally the retina display Mac Books are excellent for this purpose.
However, it seems that in Swing those devices use points rather than pixels. They allow me to change the icons to higher resolution versions as discussed here. But since we do a lot of complex graphics and components overlays I want to just use "real pixels". To be clear I am not interested in fixing blurry images or icons (not practical in my case) just to disable the pixel doubling.
There is this interesting (albeit hacky) option I found thru this question.
To my knowledge this is not possible as of JDK 1.8. The only workaround is to detect retina and use the scale affine transform when drawing.
However, detecting retina seems to be a problem since the only option that seems to be available isn't on a per monitor case which is probably not a good solution:
How can I detect whether a Mac has a Retina display from Java?
I am running Windows 7 and have set the screen DPI setting to a higher value because otherwise text and icons are too small to read on my 1080p monitor. Most programs also can be configured to either adhere to or ignore this setting on an individual basis if needed.
Unfortunately, I am unable to change the DPI for certain (all?) Java programs, such as this one:
http://www.geogebra.org/cms/en/
The program always ignores my screen DPI setting; so the application, fonts, lines, curves, etc. are nearly too small and skinny to be visible. (However, when embedded inside a Web page the applet follows the settings of the browser, and appears OK.)
Anyone know how to fix this problem on my computer or in the program's source code?