feat(theme): 实现Windows主题变更监听与动态更新

- 添加WindowsTheme工具类用于监听系统主题变更
- 实现runMonitorTopics方法监控主题变化并自动更新- 新增TopicsUpdateEvents事件类用于主题更新通知
- 重构setTopic方法使用updateTheme统一处理主题设置
-优化MainWindow背景透明度更新逻辑- 添加isSettingsVisible方法判断设置界面可见状态
- 移除RegisterTray类中的静态库加载代码
- 调整设置面板显示逻辑,支持重新显示已打开的设置窗口
-修复库加载错误日志信息
- 添加异常堆栈打印到崩溃报告组织方法中
This commit is contained in:
tzdwindows 7
2025-10-06 11:00:31 +08:00
parent adf659853d
commit 167bf6405f
7 changed files with 186 additions and 34 deletions

Binary file not shown.

View File

@@ -4,6 +4,8 @@ import com.axis.innovators.box.browser.WindowRegistry;
import com.axis.innovators.box.events.GlobalEventBus;
import com.axis.innovators.box.events.OpenFileEvents;
import com.axis.innovators.box.events.StartupEvent;
import com.axis.innovators.box.events.TopicsUpdateEvents;
import com.axis.innovators.box.util.WindowsTheme;
import com.axis.innovators.box.window.*;
import com.axis.innovators.box.plugins.PluginDescriptor;
import com.axis.innovators.box.plugins.PluginLoader;
@@ -46,6 +48,8 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.lang.instrument.Instrumentation;
import java.lang.management.*;
@@ -69,6 +73,7 @@ public class AxisInnovatorsBox {
"tzdwindows 7",
"lyxyz5223",
"\uD83D\uDC3EMr. Liu\uD83D\uDC3E",
"泽钰"
};
/** 我是总任务数 **/
@@ -188,8 +193,9 @@ public class AxisInnovatorsBox {
LibraryLoad.loadLibrary("FridaNative");
LibraryLoad.loadLibrary("ThrowSafely");
LibraryLoad.loadLibrary("DogAgent");
LibraryLoad.loadLibrary("RegisterTray");
} catch (Exception e) {
logger.error("Failed to load the 'FridaNative' library", e);
logger.error("Failed to load library", e);
}
}
@@ -222,6 +228,7 @@ public class AxisInnovatorsBox {
* 组织崩溃报告
*/
public void organizingCrashReports(Exception e) {
e.printStackTrace();
SwingUtilities.invokeLater(() -> {
String systemOut = Log4j2OutputStream.systemOutContent.toString();
String systemErr = Log4j2OutputStream.systemErrContent.toString();
@@ -713,6 +720,28 @@ public class AxisInnovatorsBox {
return tempFile;
}
/**
* 运行监控主题
*/
public void runMonitorTopics(){
WindowsTheme.setThemeChangeListener((themeName, darkTheme) -> {
logger.info("主题变更: {}, 暗主题: {}", themeName, darkTheme);
if (registrationTopic.isDarkMode() == darkTheme){
return;
}
try {
updateTheme(themeName,darkTheme);
} catch (UnsupportedLookAndFeelException e) {
throw new RuntimeException(e);
}
if (SwingUtilities.isEventDispatchThread()) {
reloadAllWindow();
} else {
SwingUtilities.invokeLater(this::reloadAllWindow);
}
});
}
private void addFileToZip(ZipOutputStream zos, File file, String entryPath) throws IOException {
if (!file.exists()) {
return;
@@ -804,7 +833,7 @@ public class AxisInnovatorsBox {
private void setTopic() {
try {
boolean isDarkMode = SystemInfoUtil.isSystemDarkMode();
boolean isDarkMode = WindowsTheme.isDarkTheme();
// 1. 默认系统主题
main.registrationTopic.addTopic(
@@ -932,16 +961,26 @@ public class AxisInnovatorsBox {
// "system:blur",true
//);
LookAndFeel defaultLaf = isDarkMode ? new FlatMacDarkLaf() : new FlatMacLightLaf();
UIManager.setLookAndFeel(defaultLaf);
main.registrationTopic.setLoading(
isDarkMode ? "system:flatMacDark_theme" : "system:flatMacLight_theme"
);
updateTheme("",isDarkMode);
} catch (Exception e) {
logger.warn("Failed to load the system facade class", e);
}
}
/**
* 更新主题
* @param themeName 主题名称
* @param isDarkMode 是否是暗主题
*/
public void updateTheme(String themeName,boolean isDarkMode) throws UnsupportedLookAndFeelException {
LookAndFeel defaultLaf = isDarkMode ? new FlatMacDarkLaf() : new FlatMacLightLaf();
UIManager.setLookAndFeel(defaultLaf);
main.registrationTopic.setLoading(
isDarkMode ? "system:flatMacDark_theme" : "system:flatMacLight_theme"
);
GlobalEventBus.EVENT_BUS.post(new TopicsUpdateEvents(themeName,isDarkMode));
}
/**
* 弹出窗口
* @param windowsJDialog 窗口
@@ -1051,7 +1090,7 @@ public class AxisInnovatorsBox {
try {
main.initLog4j2();
main.setTopic();
main.runMonitorTopics();
//main.popupLogin();
main.thread = new Thread(() -> {
try {
@@ -1155,6 +1194,12 @@ public class AxisInnovatorsBox {
isWindow = true;
ex.setVisible(true);
Toolkit.getDefaultToolkit().addPropertyChangeListener("win.xpstyle.themeName",
evt -> {
logger.info("系统主题发生变化: {}", evt.getNewValue());
ex.updateTheme();
});
if (isDebug) {
SwingUtilities.invokeLater(this::createDebugWindow);
}

View File

@@ -0,0 +1,28 @@
package com.axis.innovators.box.events;
/**
* 当主题变更时被调用
* @author tzdwindows 7
*/
public class TopicsUpdateEvents {
private final String themeName;
private final boolean darkTheme;
/**
* 构造函数
* @param themeName 主题名称
* @param darkTheme 是否是暗主题
*/
public TopicsUpdateEvents(String themeName, boolean darkTheme) {
this.themeName = themeName;
this.darkTheme = darkTheme;
}
public String getThemeName() {
return themeName;
}
public boolean isDarkTheme() {
return darkTheme;
}
}

View File

@@ -80,28 +80,31 @@ public class RegistrationSettingsItem extends WindowsJDialog {
JPanel aboutPanel = createAboutPanel();
JPanel themePanel = createThemePanel();
registrationSettingsItem.addSettings(
pluginPanel, language.getText("settings.1.title"),
null, language.getText("settings.1.tip"), "system:settings_plugins_item"
);
registrationSettingsItem.addSettings(
generalPanel, language.getText("settings.2.title"),
null, language.getText("settings.2.tip"), "system:settings_appearance_item"
);
registrationSettingsItem.addSettings(
aboutPanel, language.getText("settings.3.title"),
null, language.getText("settings.3.tip"), "system:settings_information_item"
pluginPanel, language.getText("settings.1.title"),
null, language.getText("settings.1.tip"), "system:settings_plugins_item"
);
registrationSettingsItem.addSettings(
themePanel, language.getText("settings.4.title"),
null, language.getText("settings.4.tip"), "system:settings_theme_item"
);
registrationSettingsItem.addSettings(
aboutPanel, language.getText("settings.3.title"),
null, language.getText("settings.3.tip"), "system:settings_information_item"
);
registrationSettingsItemList.add(
registrationSettingsItem
);
AxisInnovatorsBox.getMain().getMainWindow().showSettings();
// 重新显示
if (AxisInnovatorsBox.getMain().getMainWindow().isSettingsVisible()) {
AxisInnovatorsBox.getMain().getMainWindow().showSettings();
}
}
private static JPanel createThemePanel() {

View File

@@ -12,11 +12,6 @@ import java.util.List;
*/
public class RegisterTray {
static {
LibraryLoad.loadLibrary("RegisterTray");
//System.load("C:\\Users\\Administrator\\source\\repos\\RegisterTray\\x64\\Release\\RegisterTray.dll");
}
/**
* 托盘菜单项构建器(流畅接口)
*/

View File

@@ -0,0 +1,64 @@
package com.axis.innovators.box.util;
/**
* Windows主题变更监听器
* @author tzdwindows 7
*/
public class WindowsTheme {
/**
* 设置主题改变监听器
* @param listener 监听器
*/
public static native void setThemeChangeListener(ThemeChangeListener listener);
/**
* 主题改变监听器
*/
public interface ThemeChangeListener {
/**
* 当主题改变时调用
* @param themeName 主题名称
* @param darkTheme 是否是暗主题
*/
void themeChanged(String themeName,boolean darkTheme);
}
/**
* 获取当前是否为暗色主题
* @return true-暗色主题, false-亮色主题
*/
public static native boolean isDarkTheme();
/**
* 获取当前主题名称
* @return 主题名称
*/
public static native String getThemeName();
//public static void main(String[] args) {
// try {
// System.load("C:\\Users\\Administrator\\source\\repos\\RegisterTray\\x64\\Release\\RegisterTray.dll");
//
// // 先测试直接获取主题信息的方法
// System.out.println("Current topic Name: " + WindowsTheme.getThemeName());
// System.out.println("Is it a dark theme: " + WindowsTheme.isDarkTheme());
//
// WindowsTheme.setThemeChangeListener(new WindowsTheme.ThemeChangeListener() {
// @Override
// public void themeChanged(String themeName, boolean darkTheme) {
// System.out.println("The theme has changed: " + themeName + " is dark theme: " + darkTheme);
// }
// });
//
// System.out.println("Start listening for theme changes... Press Enter to exit");
//
// System.in.read();
//
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// WindowsTheme.setThemeChangeListener(null);
// }
//}
}

View File

@@ -155,19 +155,7 @@ public class MainWindow extends JFrame {
this.backgroundOpacity = Math.max(0.0f, Math.min(1.0f, opacity));
this.cachedBlurredBackground = null;
this.cachedBackgroundSize = null;
// 重新绘制窗口
if (AxisInnovatorsBox.getMain().isWindow()) {
AxisInnovatorsBox.getMain().reloadAllWindow();
}
else {
getContentPane().removeAll();
revalidate();
repaint();
initUI();
updateTheme();
revalidate();
}
AxisInnovatorsBox.getMain().reloadAllWindow();
}
/**
@@ -965,6 +953,36 @@ public class MainWindow extends JFrame {
return wrapper;
}
/**
* 判断设置界面是否打开
* @return 设置界面是否可见
*/
public boolean isSettingsVisible(){
if (dialog == null) {
return false;
}
if (!dialog.isDisplayable()) {
dialog = null;
return false;
}
if (!dialog.isVisible()) {
return false;
}
try {
if (dialog.getParent() != this && dialog.getOwner() != this) {
dialog = null;
return false;
}
} catch (Exception e) {
dialog = null;
return false;
}
return true;
}
private JPanel createToolCard(ToolItem tool) {
JPanel card = new JPanel() {
@Override
@@ -1368,7 +1386,6 @@ public class MainWindow extends JFrame {
dialog.setSize(750, 550);
dialog.setLocationRelativeTo(this);
// 使用 JLayer + LayerUI 来对整个内容做统一的淡入 + 下滑(仿 Apple 风格)动画,
// 这样子组件也会跟随一起动画,而不是只有背景绘制发生变化。
JPanel inner = new JPanel(new BorderLayout());