feat(gui): 添加系统托盘功能并优化 UI

- 实现系统托盘支持,包含打开主界面、反编译工具和退出程序的菜单项
- 添加窗口关闭时隐藏而不是退出的功能
-优化托盘图标,使用圆角图像
- 增加中文字体支持和全局字体设置- 移除 AIChatDialog 中的 MathJax 配置- 更新 BoxClassLoader,添加 com.dustinredmond 包的访问权限
- 在 build.gradle 中添加 SystemTray4J 和 JavaFX相关依赖
This commit is contained in:
tzdwindows 7
2025-03-16 12:16:31 +08:00
parent d19eb92e4a
commit 6b0a81175e
4 changed files with 135 additions and 11 deletions

View File

@@ -114,6 +114,13 @@ dependencies {
implementation 'com.kitfox.svg:svg-salamander:1.0'
implementation 'com.vladsch.flexmark:flexmark:0.64.8'
// SystemTray4J 核心库
implementation 'com.github.kwhat:jnativehook:2.2.2'
implementation 'com.dustinredmond.fxtrayicon:FXTrayIcon:4.0.1' // 增强版
// JavaFX 模块
implementation 'org.openjfx:javafx-graphics:21'
}
// 分离依赖项到 libs 目录

View File

@@ -1,6 +1,7 @@
package com.axis.innovators.box.gui;
import com.axis.innovators.box.AxisInnovatorsBox;
import com.axis.innovators.box.decompilation.gui.ModernJarViewer;
import com.axis.innovators.box.events.*;
import com.axis.innovators.box.register.RegistrationSettingsItem;
import com.axis.innovators.box.register.LanguageManager;
@@ -11,11 +12,14 @@ import org.apache.logging.log4j.Logger;
import javax.swing.*;
import javax.swing.Timer;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.PanelUI;
import javax.swing.plaf.basic.BasicScrollBarUI;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
@@ -34,6 +38,8 @@ public class MainWindow extends JFrame {
private final List<ToolCategory> categories = new ArrayList<>();
private final boolean isBackground = true;
private final boolean isBlur = true;
private SystemTray systemTray;
private TrayIcon trayIcon;
public MainWindow() {
setIconImage(LoadIcon.loadIcon("logo.png", 32).getImage());
@@ -63,6 +69,8 @@ public class MainWindow extends JFrame {
setSize(1200, 800);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
getContentPane().setBackground(new Color(0, 0, 0, 0));
JPanel mainPanel = new JPanel();
@@ -76,18 +84,128 @@ public class MainWindow extends JFrame {
mainPanel.add(createCategoryTabs(), BorderLayout.CENTER);
add(mainPanel);
createSystemTray();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
setVisible(false);
}
});
}
private BufferedImage toBufferedImage(Image img) {
if (img instanceof BufferedImage) {
return (BufferedImage) img;
private void createSystemTray() {
if (!SystemTray.isSupported()) {
logger.error("系统托盘不支持!");
return;
}
BufferedImage bimage = new BufferedImage(
img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
return bimage;
// 初始化系统托盘
systemTray = SystemTray.getSystemTray();
// 1. 加载并处理圆角图标(修正图像类型)
ImageIcon rawIcon = LoadIcon.loadIcon("logo.png", 64);
Image roundedImage = createRoundedIcon(rawIcon.getImage(), 16);
// 2. 创建支持中文的弹出菜单
PopupMenu popup = new PopupMenu();
// 3. 创建菜单项使用标准AWT组件
MenuItem openItem = createBaseMenuItem("打开主界面", e -> setVisible(true));
MenuItem decompileItem = createBaseMenuItem("打开反编译工具", e ->
new ModernJarViewer(null).setVisible(true));
MenuItem exitItem = createBaseMenuItem("退出程序", e -> AxisInnovatorsBox.getMain().quit());
// 4. 构建菜单结构
popup.add(openItem);
popup.addSeparator();
popup.add(decompileItem);
popup.addSeparator();
popup.add(exitItem);
// 5. 创建托盘图标
trayIcon = new TrayIcon(roundedImage, "轴创工具箱", popup);
trayIcon.setImageAutoSize(true);
// 6. 添加事件监听
addTrayEventListeners();
try {
systemTray.add(trayIcon);
} catch (AWTException ex) {
logger.error("添加系统托盘图标失败", ex);
}
}
// 基础菜单项创建方法(解决方法不存在问题)
private MenuItem createBaseMenuItem(String text, ActionListener action) {
MenuItem item = new MenuItem(text);
item.addActionListener(action);
return item;
}
// 圆角图标生成(修正版)
private Image createRoundedIcon(Image source, int cornerRadius) {
int size = Math.max(source.getWidth(null), source.getHeight(null));
BufferedImage output = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = output.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 创建剪切路径
RoundRectangle2D roundRect = new RoundRectangle2D.Float(0, 0, size, size, cornerRadius, cornerRadius);
g2.setClip(roundRect);
g2.drawImage(source, 0, 0, size, size, null);
g2.dispose();
return output;
}
// 添加事件监听
private void addTrayEventListeners() {
// 双击恢复窗口
trayIcon.addActionListener(e -> setVisible(true));
// 右键菜单触发兼容处理
trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
trayIcon.getPopupMenu().show(e.getComponent(), e.getX(), e.getY());
}
}
});
}
// 初始化中文字体在main方法或构造函数中调用
private void initChineseFont() {
String[] fontPriority = {
"Microsoft YaHei",
"PingFang SC",
"SimSun",
Font.DIALOG
};
for (String fontName : fontPriority) {
if (isFontAvailable(fontName)) {
setGlobalFont(new Font(fontName, Font.PLAIN, 12));
break;
}
}
}
// 字体可用性检查
private boolean isFontAvailable(String fontName) {
return Arrays.asList(GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames())
.contains(fontName);
}
// 全局字体设置
private void setGlobalFont(Font font) {
FontUIResource fontRes = new FontUIResource(font);
UIManager.put("MenuItem.font", fontRes);
UIManager.put("Menu.font", fontRes);
}
/**

View File

@@ -26,7 +26,7 @@ public class BoxClassLoader extends URLClassLoader {
"java.", "javax.", "sun.", "com.sun.", "jdk.",
"org.xml.", "org.w3c.", "org.apache.",
"javax.management.", "javax.swing."
, "javafx.","org.jnativehook."
, "javafx.","org.jnativehook.","com.dustinredmond."
);
}

View File

@@ -479,7 +479,6 @@ public class AIChatDialog extends JFrame {
Node document = markdownParser.parse(markdown);
processedHtml = htmlRenderer.render(document);
// 强化 MathJax 配置
processedHtml = String.format("""
<!DOCTYPE html>
<html>