无法检测到Windows经典主题处于活动状态。

9

我正在调用UIManager.getSystemLookAndFeelClassName()方法,结果返回WindowsLookAndFeel,即使将当前主题设置为WindowsClassicLookAndFeel。但是我希望得到WindowsClassicLookAndFeel。 问题是如何检测Windows经典主题是否处于活动状态。


1
我不知道答案,但提供答案的人似乎甚至没有阅读问题。Windows XP,Vista和7都有它们的标准主题,但也可以使其看起来像Windows 2000(经典主题)。问题是如何检测用户将Windows设置为哪个主题。 - Ricky Clarkson
从这个问题中,我理解他是将“主题”设置为 WindowsClassicLookAndFeel,它是Java中的LaF,并想知道是否已安装。 - Denis Tulskiy
3个回答

15

看起来你注册账号的唯一目的就是问这个问题,而我现在也特地注册了账号来回答它!我本来是在谷歌上搜索完全不同的东西时被吸引了,然后做了一些实验,这就是我发现的:

关于WindowsClassicLookAndFeel,你说得对。这个类继承了WindowsLookAndFeel,但没有覆盖任何内容,即使在 Windows Classic 模式下也似乎根本没有使用。所以,我查看了WindowsLookAndFeel的代码,并找到了一些有趣的内部代码,其中引用了包私有类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();
    }
}
你可以将这个类导入到你的程序中,并在任何时候设置你的 Look&Feel 后调用 isWindowsClassicLAF() 方法。我还提供了一个如何在运行时监听主题更改的示例。
这在 XP 上经过了测试。如果用户从一个 XP 主题更改到另一个主题,监听器不会触发,但是如果用户从一个主题更改为经典模式或反之,则会触发。
希望这能帮到你!

2

我不太确定你在问什么。

如果你想知道SWING当前使用的主题/外观,可以尝试使用UIManager.getSystemLookAndFeelClassName()

如果你想知道Windows正在使用哪个主题 - 我不知道。可能不太容易找到。

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


是的,像这样,但是还有com.sun.java.swing.plaf.windows.WindowsLookAndFeel和com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel,但是即使应用了经典的Windows主题,UIManager.getSystemLookAndFeelClassName()仍然只返回com.sun.java.swing.plaf.windows.WindowsLookAndFeel。 - fland
你甚至没有阅读方法正在做什么,就给出了一个Javadoc的链接。 - Denis Tulskiy
@tulskiy最近重新表达了他的问题,因此我只能猜测他想要什么。因此我的答案不再有太多意义。 - Tedil

-1

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


1
它没有回答如何检测经典主题是否已安装的问题。 - om-nom-nom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接