How to get Java swing application to respect OS DPI settings - java

Is there a way to set DPI in Swing? For the whole application? And if there is, how do I set it to the value of the system DPI?
I guess there must be a way to do it, as I mentioned this feature must have benn added to NetBeans in some of latest versions...
Thank you for reading.

I think it would depend on the Look and Feel you're using.
As far as I know Substance LAF honors the current desktop DPI settings.
Here is some related info https://pushingpixels.dev.java.net/files/documents/7463/95862/dpi-bof.pdf

Related

What are font properties of titlebar in JOptionPane?

How to get the font properties of titlebar in JOptionPane. I am using linux OS system. We can get font properties of other java component using getFont API but as titlebar is OS dependent (native), what is the way to get font properties of titlebar ?
You can't really control titlebar decorations on Linux before Wayland, which is not generalized yet, and even in a Wayland world that will depend on the desktop environment, its toolkit, and how much leeway it gives to individual apps.
Probably a lost cause if you add the Java/native toolkit barrier. Java is not even using GTK3 yet, I doubt GTK2 will ever get more than minimal Wayland love and exploiting Wayland from GTK3 will probably require deeper support than just a minimal GTK2 glue replacement.
You may have more luck with SWT.
OpenJDK GTK3 support

How to set the DPI of Java Swing apps on Windows/Linux?

If you have an monitor with a DPI over 150 (such as Macbook Pro), you may also find the problem: the font on the Java Swing app is too small for high DPI monitor, and I cannot change the font size at all ( It ignores the Windows DPI directly, only displaying the very original DPI-->96 ). I can do nothing but changing the screen resolution, which could absolutely make everything blurry on LCD.
Yes, I have a laptop with a high DPI monitor, 15.6' with 1920x1080 resolution, some Java desktop apps look very small on my laptop, such as Matlab, Burpsuite etc. I have been searching the Internet for a very very long time, but still cannot find a method for the problem. I know I can change the JRE fonts through JRE_HOME/lib/font/fontconfig.properties.src, but I cannot find any place to set the default font size or DPI for Java desktop fonts.
Does the problem have no solution? Do you have a high DPI monitor? How do you do with such apps? Does Swing give up high DPI users?
I'm currently investigating this issue on Windows. Here's what I found:
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
Short answer: You need to run it on JRE 9+.
Long answer:
This is because the Java runtime declared itself to be "DPI-aware" but didn't really supported it for AWT and Swing. Java applications were sized and rendered based on pixels rather than being properly scaled, this included HiDPI displays.
Anyways, this has been recently solved.
See the issue JEP 263: HiDPI Graphics on Windows and Linux
and the upgrade.
So, increasing the font size does not work (because it does not increase the rest of the things); the jvm argument -Dsun.java2d.dpiaware=false does not work (because it is not really supported); and the manifest file + registry edit (for Windows) just does not work.
Solution: You need to run it on JRE 9+ because it really supports this feature.
This answer solved the issue on my 4K-screen Ubuntu laptop.
In the application's config file, I added the -Dsun.java2d.uiScale=2.5 Java parameter and now, upon executing, the application is scaled well and is usable.
It appears that on Linux (Gtk) you can work around this by scaling the Apps DPI using the following before starting the app.
export GDK_SCALE=2
(You can also reduce you monitor resolution but that's no solution at all).
On Linux, it doesn't seem possible to do scaling with any Swing look and feel, according to my experiments. However, it is possible to do it using a hack involving VNC, vncdesk. Here is my configuration for running gradle --gui under vncdesk:
.vncdesk/1/settings.ini:
[desktop]
width = 1050
height = 650
[window]
title = gradle
name = gradle in vncdesk
class = GradleInVncdesk
scale_factor = 2
.vncdesk/1/startup:
#!/bin/sh
cd "$INVOCATION_DIR"
matchbox-window-manager&
exec gradle --gui "$#"
I managed to solve it following these instructions: Link.
It's in German, but I will translate the important stuff.
Create this registry-key:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide]
"PreferExternalManifest"=dword:00000001
Create a manifest file with this content:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="amd64" publicKeyToken="1fc8b3b9a1e18e3b">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</ms_windowsSettings:dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
Copy it into the bin directory where the java.exe and javaw.exe is inside and named it java.exe.manifest and javaw.exe.manifest (You will have two files with the same content but different names).
HTH.
Bernd
As #demented hedgehog said setting the GDK_SCALE=2 environment variable does work under Linux.
If you are using JetBrains IntelliJ you can set Enviroment variables just for your project under Edit configurations > Build and Run > Enviroment variables
You can see below where to put the GDK_SCALE=2.

inconsolata and netbeans

When I installed inconsolata everything looked fine, however when I tried viewing it on netbeans it look like this:
I tried using both the ttf and otf versions and they both looked messed up.
Is this a java issue? Win 7 64 bit issue? Is there any way to fix this?
You could try disabling font antialiasing in NetBeans.
Open up your netbeans.conf
As part of the netbeans_default_options section add -J-Dswing.aatext=false -J-Dawt.useSystemAAFontSettings=off.
Edit: fvu also provided a helpful link to a relevant section in the NetBeans font rendering FAQ.
If you want to play around with NetBeans font rendering settings, take a look at http://wiki.netbeans.org/FaqFontRendering
Unfortunately, what this article concludes is that default font rendering settings provide the best possible experience. At least under Windows. I have tried all the possibilities with Inconsolata and defaults provide the the best look indeed.
As a workaround, you can try two things:
Decrease contrast of your color scheme, i.e. by decreasing lightness of a background and/or increasing lightness of your font. It makes font rendering issues less visible.
Use NegativeScreen: http://arcanesanctum.net/negativescreen/
You may find your experience improved, but this is up to your personal preference.
It's not just NetBeans, although it is probably not simply the Inconsolata font's fault either. There seems to be a problem at the level of the underlying Java system that NetBeans is built on. I say this because the exact same problem shows up in the IDEs created by Jetbrains -- IntelliJ IDEA, WebStorm, PyCharm, and possibly others.

ExpandBar/ExpandItem background/foreground colors in Java SWT

I'm looking to manage colors of headers of my expandItem in SWT, and I'm not able to change the background or the foreground (swt gtk 32bit) or only background (swt win 64).
Is there some particular way to do that?
I'm already setting:
exp_bar.setBackground(new Color(display, GUISetting.MAIN_BACKGROUND));
exp_bar.setForeground(new Color(display, GUISetting.MAIN_TEXT_COLOR));
But this does not seem to work.
Any ideas?
According to this page, this behaviour is intended. The widgets are supplied by the OS. The OS uses a texture and SWT decided, that you cannot set the color on a widget with a texture.
There is a bug report here that you can support.
However, these posts are quite old (2006). Maybe it was fixed till now, but I couldn't find anything...
In SWT, these widgets are supplied by OS. if you look at documentation setBackground(), it says the parameters are just hints. they might be honored or not, it all depends on OS.

Adding a contribution to the windows task bar in java - similar to laptop battery widgets

I am trying to make a contribution to the windows task bar so when i minimize my app it docks itself into the windows task bar , the best way of describing this is by looking at a picture I have drawn:
If anybody knows if this is possible or how to do it please let me know.
I am well aware of the ability to add an icon to the system tray - but this is slightly different.
Thanks in advance,
Andy
You should probably have to use JNI or JNA to achieve this - wrapping the native windows API seems like the most viable idea. It'll greatly diminish the value of using Java, however - using JNI/JNA should always be considered last resort...
Take a look at SWT. This will definitely be a platform specific solution but I am assuming this isn't an issue for you.
SWT (Beginning with 3.6 which just went gold) has a TaskBar class and corresponding TaskItem classes for each item in the TaskBar. I don't think the TaskItem class is going to be powerful enough to do what you are asking for, but by looking at the source it will provide you insight into the low level Windows calls that you can access to get this done.
The SWT version for Windows will have a low level platform specific API that should get you where you want to go. Basically they have done all the JNA/JNI work for you. I am not a Windows programmer so I can't give you more details, but hopefully this will point you in the right direction.
You just need to use the System Tray functionality available in Java 6.
If you look at the More Information section at the bottom of that page it has links to the System Tray API and an example project.
Could you hide your application on minimize and then add an icon for it to the system tray that, when clicked, unhides your application?

Categories

Resources