9

我正在调用 UIManager.getSystemLookAndFeelClassName()。并获得 WindowsLookAndFeel 的结果,即使将当前主题设置为 WindowsClassicLookAndFeel。但我期待 WindowsClassicLookAndFeel。问题是如何检测 Windows 经典主题现在处于活动状态

4

3 回答 3

15

看来你是特地报名来问这个问题的,现在我特地报名来回答这个问题!我在谷歌上搜索完全不同的东西,但我很感兴趣并做了一些实验,这就是我发现的:

你是对的WindowsClassicLookAndFeel。此类扩展WindowsLookAndFeel但不覆盖任何内容,并且似乎根本没有使用,即使 Windows 经典处于活动状态也是如此。因此,我查看了代码WindowsLookAndFeel并发现了一些引用 package-private 类的有趣内部代码XPStyle。此类似乎是一个单例,并且 getter 方法getXP()仅在“XP”主题处于活动状态时才返回其实例:

/** 
 * 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;
}

有趣的是,代码再次检查,WindowsClassicLookAndFeel但我们知道它不再使用(也许它已更改)......但最好的部分是检查桌面属性win.xpstyle.themeActive从代码中提取它,我进行了以下测试:

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

您可以将此类导入您的程序并isWindowsClassicLAF()在任何时候设置您的外观后调用该方法。我还提供了一个示例,说明如何在运行时监听主题的变化。

这是在 XP 上经过试验和测试的。如果用户从一个 XP 主题更改为另一个,侦听器不会触发,但如果用户从一个主题更改为 Classic,反之亦然。

我希望这会有所帮助!

于 2010-12-08T11:16:54.930 回答
2

我不太确定你在问什么。

如果您询问 SWING 当前正在使用哪个主题/外观,请尝试 UIManager.getSystemLookAndFeelClassName()

如果您想找出 Windows 使用的是哪个主题 - 我不知道。可能不太容易找到它。

编辑:快速破解可能是(除了使用 JNA/JNA 直接查询某些 Windows API 正在使用哪个主题)将创建一个新的 JFrame,将其放置在某个区域,捕获该边框的一小部分并将其与边框样本(您需要预先创建并随代码一起发布,以便能够以编程方式比较刚刚拍摄的屏幕捕获位和您发布的所有边框图像)

于 2010-09-07T13:37:28.047 回答
-1

UIManager.getLookAndFeel()返回当前安装的 LaF。getSystemLookAndFeel()返回看起来像当前系统主题的外观,例如 Windows 上的 WindowsLookAndFeel Linux 上的 GTKLookAndFeel Solaris 上的 MOtifLookAndFeel 等。

于 2010-09-07T15:18:40.757 回答