From 9da8953253d2a4e59b6e4902cfb588e73af76d74 Mon Sep 17 00:00:00 2001 From: tzdwindows 7 <3076584115@qq.com> Date: Sun, 16 Mar 2025 12:17:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(gui):=20=E6=B7=BB=E5=8A=A0=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E6=89=98=E7=9B=98=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现系统托盘支持,包含打开主界面、反编译工具和退出程序的菜单项 - 添加窗口关闭时隐藏而不是退出的功能 -优化托盘图标,使用圆角图像 - 增加中文字体支持和全局字体设置- 移除 AIChatDialog 中的 MathJax 配置- 更新 BoxClassLoader,添加 com.dustinredmond 包的访问权限 - 在 build.gradle 中添加 SystemTray4J 和 JavaFX相关依赖 --- .../innovators/box/gui/ModernTrayApp.java | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 src/main/java/com/axis/innovators/box/gui/ModernTrayApp.java diff --git a/src/main/java/com/axis/innovators/box/gui/ModernTrayApp.java b/src/main/java/com/axis/innovators/box/gui/ModernTrayApp.java new file mode 100644 index 0000000..0b2cbcd --- /dev/null +++ b/src/main/java/com/axis/innovators/box/gui/ModernTrayApp.java @@ -0,0 +1,251 @@ +package com.axis.innovators.box.gui; + +import com.axis.innovators.box.AxisInnovatorsBox; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.RoundRectangle2D; + +/** + * 创建一个具有圆角效果的系统托盘图标,并添加右键菜单。 + * (未完成) + * @author tzdwindows 7 + */ +public class ModernTrayApp { + private static final int ITEM_WIDTH = 145; + private static final int ITEM_HEIGHT = 29; + private static final int ICON_SIZE = 16; + private static final int WINDOW_CORNER = 6; + private static final Color MENU_BG_COLOR = new Color(250, 250, 250); + + private TrayIcon trayIcon; + private JPopupMenu popupMenu; + private JWindow mainWindow; + + public static void main(String[] args) { + + if (!System.getProperty("os.name").contains("Windows")) { + JOptionPane.showMessageDialog(null, "本程序仅支持Windows系统"); + return; + } + new ModernTrayApp().initTray(); + } + + private void initTray() { + try { + // 1. 加载并缩放托盘图标 + Image trayImage = LoadIcon.loadIcon("logo.png", 32).getImage(); + trayIcon = new TrayIcon(trayImage, "轴创工具箱"); + trayIcon.setImageAutoSize(true); + // 2. 创建主窗口 + createMainWindow(); + + // 3. 创建圆角菜单 + createRoundPopupMenu(); + + // 4. 配置系统托盘 + SystemTray.getSystemTray().add(trayIcon); + trayIcon.addMouseListener(new TrayMouseListener()); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void createMainWindow() { + mainWindow = new JWindow() { + @Override + public void paint(Graphics g) { + // 创建临时图形上下文 + Graphics2D g2 = (Graphics2D) g.create(); + + // 启用高质量渲染 + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + + // 绘制透明背景(关键步骤) + g2.setComposite(AlphaComposite.Clear); + g2.fillRect(0, 0, getWidth(), getHeight()); + g2.setComposite(AlphaComposite.SrcOver); + + // 绘制圆角面板 + g2.setColor(MENU_BG_COLOR); + g2.fillRoundRect(0, 0, getWidth(), getHeight(), WINDOW_CORNER, WINDOW_CORNER); + + // 绘制边框 + g2.setColor(new Color(220, 220, 220)); + g2.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, WINDOW_CORNER, WINDOW_CORNER); + + g2.dispose(); + } + }; + + mainWindow.setSize(ITEM_WIDTH, ITEM_HEIGHT * 3 + 10); + mainWindow.setShape(new RoundRectangle2D.Float(0, 0, + mainWindow.getWidth(), mainWindow.getHeight(), WINDOW_CORNER, WINDOW_CORNER)); + + + // 合并后的焦点监听器 + mainWindow.addWindowFocusListener(new WindowAdapter() { + @Override + public void windowLostFocus(WindowEvent e) { + closeMenuAndWindow(); + } + }); + mainWindow.setType(Window.Type.POPUP); + } + + private void closeMenuAndWindow() { + SwingUtilities.invokeLater(() -> { + // 添加淡出动画 + new Thread(() -> { + for (float opacity = 1.0f; opacity > 0; opacity -= 0.1f) { + final float finalOpacity = opacity; + SwingUtilities.invokeLater(() -> { + mainWindow.setOpacity(finalOpacity); + }); + try { Thread.sleep(20); } catch (InterruptedException e) {} + } + SwingUtilities.invokeLater(() -> { + popupMenu.setVisible(false); + mainWindow.setVisible(false); + mainWindow.setOpacity(1.0f); // 重置透明度 + }); + }).start(); + }); + } + + + private void updateWindowShape() { + RoundRectangle2D shape = new RoundRectangle2D.Float( + 0, 0, + mainWindow.getWidth(), mainWindow.getHeight(), + WINDOW_CORNER, WINDOW_CORNER + ); + mainWindow.setShape(shape); + } + + private void updateWindowSize(int width, int height) { + mainWindow.setSize(width, height); + updateWindowShape(); + } + + private void createRoundPopupMenu() { + popupMenu = new JPopupMenu(){ + @Override + protected void firePopupMenuCanceled() { + closeMenuAndWindow(); + super.firePopupMenuWillBecomeInvisible(); + } + }; + popupMenu.setLayout(new GridLayout(0, 1, 0, 1)); + + JPanel customSeparator = new JPanel() { + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(new Color(220, 220, 220)); + g.fillRect(5, getHeight()/2, getWidth()-10, 1); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(ITEM_WIDTH, 4); + } + }; + customSeparator.setOpaque(false); + + popupMenu.add(ComponentFactory.createTextComponent("AxisInnovatorsBox", + new Color(0, 0, 0), + 15, + new Dimension(ITEM_WIDTH, 4))); + popupMenu.add(ComponentFactory.createTextComponent(" ————" + + AxisInnovatorsBox.getVersion(), + new Color(83, 83, 83), + 12, + new Dimension(ITEM_WIDTH, 4))); + + popupMenu.add(customSeparator); + addStyledMenuItem("打开主界面", "home.png"); + addStyledMenuItem("Java反编译", "decompile.png"); + popupMenu.add(customSeparator); + + addStyledMenuItem("退出程序", "exit.png"); + } + + private void addStyledMenuItem(String text, String iconPath) { + JMenuItem item = new JMenuItem(text) { + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + // 绘制背景 + if (isArmed()) { + g2.setColor(new Color(161, 161, 161)); + g2.fillRoundRect(0, 0, getWidth(), getHeight(), 4, 4); + } + + // 绘制图标 + Image icon = LoadIcon.loadIcon(iconPath, ICON_SIZE).getImage(); + g2.drawImage(icon, 8, (ITEM_HEIGHT - ICON_SIZE)/2, null); + + // 绘制文本 + g2.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + g2.setColor(Color.DARK_GRAY); + g2.drawString(text, 28, (ITEM_HEIGHT + g2.getFontMetrics().getAscent())/2 - 1); + + g2.dispose(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(ITEM_WIDTH, ITEM_HEIGHT); + } + }; + + item.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); + item.setOpaque(false); + popupMenu.add(item); + } + + private class TrayMouseListener extends MouseAdapter { + @Override + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + showMenu(e.getX(), e.getY()); + } + } + + private void showMenu(int x, int y) { + Point mousePos = MouseInfo.getPointerInfo().getLocation(); + Point menuLocation = calculateMenuPosition(mousePos); + + mainWindow.setLocation(menuLocation); + mainWindow.setVisible(true); + popupMenu.show(mainWindow.getContentPane(), 0, 0); + } + + private Point calculateMenuPosition(Point pos) { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + int menuHeight = mainWindow.getHeight(); + + // 默认显示在鼠标右上方 + int finalX = pos.x + 16; // 向右偏移16px + int finalY = pos.y - menuHeight - 8; // 向上偏移8px + + // 右侧边界检测 + if (finalX + ITEM_WIDTH > screenSize.width) { + finalX = screenSize.width - ITEM_WIDTH - 8; + } + + // 顶部溢出检测 + if (finalY < 0) { + finalY = pos.y + 16; // 改为显示在下方 + } + + return new Point(finalX, finalY); + } + } +} \ No newline at end of file