can't detect that windows classic theme active
I am calling UIManager.getSystemLookAndFeelClassName(). And get as result WindowsLookAndFeel, even when开发者_如何学运维 setting current theme to WindowsClassicLookAndFeel. But I expect WindowsClassicLookAndFeel. Question is how can I detect that windows classic theme is now active
It looks like you signed up specifically to ask this question, and now I'm signing up specifically to answer it! I was Googling for something completely different but I was intrigued and did some experimenting, and here's what I found:
You're right about the WindowsClassicLookAndFeel
. This class extends WindowsLookAndFeel
but doesn't override anything, and doesn't appear to be used at all, even when Windows Classic is active. So, I looked into the code of WindowsLookAndFeel
and found some interesting internal code that references the package-private class XPStyle
. This class appears to be a singleton and the getter method, getXP()
, only returns its instance if the 'XP' theme is active:
/**
* Get the singleton instance of this class
*
* @return the singleton instance of this class or null if XP styles
* are not active or if this is not Windows XP
*/
static synchronized XPStyle getXP() {
if (themeActive == null) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
themeActive =
(Boolean)toolkit.getDesktopProperty("win.xpstyle.themeActive");
if (themeActive == null) {
themeActive = Boolean.FALSE;
}
if (themeActive.booleanValue()) {
GetPropertyAction propertyAction =
new GetPropertyAction("swing.noxp");
if (AccessController.doPrivileged(propertyAction) == null &&
ThemeReader.isThemed() &&
!(UIManager.getLookAndFeel()
instanceof WindowsClassicLookAndFeel)) {
xp = new XPStyle();
}
}
}
return xp;
}
Interestingly, the code checks for the WindowsClassicLookAndFeel
again but we know that this is no longer used (perhaps it's changed)... But the best part is the check for the desktop property win.xpstyle.themeActive
Extracting this from the code, I made the following test:
package test;
import java.awt.Toolkit;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.UIManager;
public class WindowsClassicThemeDetector {
public static boolean isWindowsLAF() {
return UIManager.getLookAndFeel().getID().equals("Windows");
}
public static boolean isWindowsClassicLAF() {
return isWindowsLAF()
&& !(Boolean) Toolkit.getDefaultToolkit().getDesktopProperty(
"win.xpstyle.themeActive");
}
public static void main(String... args) throws Exception {
// Apply the system look and feel (which will be Windows)
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
// Check the initial theme state on startup
System.out.println(UIManager.getLookAndFeel().getClass());
System.out.println("Windows classic is initially: " + isWindowsClassicLAF());
// Register a listener in case the theme changes during runtime.
Toolkit.getDefaultToolkit().addPropertyChangeListener("win.xpstyle.themeActive",
new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("Windows classic is now: " + isWindowsClassicLAF());
}
});
// Wait until user presses ENTER in the console and then exit.
System.in.read();
}
}
You can import this class into your program and call the isWindowsClassicLAF()
method after setting your Look&Feel at any point. I've also given an example of how you can listen out for changes to the theme at run-time.
This is tried and tested on XP. If the user changes from one XP theme to another, the listener doesn't fire, but if the user changes from a theme to Classic, or vice-versa, it will.
I hope that helps!
I'm not quite sure what you are asking.
If you are asking which theme/look and feel SWING is currently using, try UIManager.getSystemLookAndFeelClassName().
If you are trying to find out which theme Windows is using - I don't know. Probably not quite easy to find that out.
Edit: A quick hack might be (apart from using JNA/JNA to query some Windows API directly which theme is being used) would be creating a new JFrame, place it in some area, capture a small part of that border and compare it with samples of borders (which you need to create beforehand and ship with your code, as to be able to programmatically compare the just-taken-screen-capture-bit and all border-images you ship)
UIManager.getLookAndFeel()
returns currently installed LaF. getSystemLookAndFeel()
returns look and feel that would look as a current system's theme, e.g. WindowsLookAndFeel on windows GTKLookAndFeel on Linux MOtifLookAndFeel on Solaris etc.
精彩评论