diff --git a/build.gradle b/build.gradle index a82027f..1650a6d 100644 --- a/build.gradle +++ b/build.gradle @@ -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 目录 diff --git a/src/main/java/com/axis/innovators/box/gui/MainWindow.java b/src/main/java/com/axis/innovators/box/gui/MainWindow.java index 719cf1e..6fccccf 100644 --- a/src/main/java/com/axis/innovators/box/gui/MainWindow.java +++ b/src/main/java/com/axis/innovators/box/gui/MainWindow.java @@ -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 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); } /** diff --git a/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java b/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java index 5495fbf..eb78352 100644 --- a/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java +++ b/src/main/java/com/axis/innovators/box/plugins/BoxClassLoader.java @@ -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." ); } diff --git a/src/main/java/com/axis/innovators/box/ui/AIChatDialog.java b/src/main/java/com/axis/innovators/box/ui/AIChatDialog.java index b308f30..2058379 100644 --- a/src/main/java/com/axis/innovators/box/ui/AIChatDialog.java +++ b/src/main/java/com/axis/innovators/box/ui/AIChatDialog.java @@ -479,7 +479,6 @@ public class AIChatDialog extends JFrame { Node document = markdownParser.parse(markdown); processedHtml = htmlRenderer.render(document); - // 强化 MathJax 配置 processedHtml = String.format("""