侧边栏壁纸
博主头像
sirgo的博客 博主等级

每天进步一点点,一年之后你会看到巨大的变化

  • 累计撰写 58 篇文章
  • 累计创建 46 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Java AWT的托盘Tray不能使用中文问题

sirgo
2025-06-06 / 0 评论 / 0 点赞 / 2 阅读 / 0 字

问题现象:

Java8-java21 目前使用的java21无法使用awt的TrayIcon类创建中文菜单。 大部分的解决方案是:添加VM参数:

 -Dfile.encoding=GBK 

但是项目其他模块如文件读写、字符串都是UTF-8 改变项目的编码为GBK不现实。

经过查找发现这个问题对于awt的PopupMenu目前无解(java21也不行),只有使用swring的JPopupMenu可以

参考:https://lanlan2017.github.io/blog/2b294c47/

完整代码:

package top.sirgo.printer.gui;

import javafx.application.Platform;
import javafx.stage.Stage;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

public class Tray {
    private final Stage primaryStage;
    private TrayIcon trayIcon;
    private JDialog jDialog = null;
    private JPopupMenu jPopupMenu = null;

    public Tray(Stage primaryStage, URL iconUrl, String title) {
        this.primaryStage = primaryStage;
        initTray(iconUrl, title);
    }

    private void initTray(URL iconUrl, String title) {
        if (!SystemTray.isSupported()) return;

        // 创建菜单
        JPopupMenu awtMenu = createJpopMenu();

        // 加载托盘图标
        Image image = createTrayImage(iconUrl);

        // 创建托盘图标
        trayIcon = new TrayIcon(image, title);
        trayIcon.setImageAutoSize(true);

        // 添加事件监听
        addTrayListeners();

        try {
            SystemTray.getSystemTray().add(trayIcon);
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }

    private PopupMenu createMenu() {
        PopupMenu menu = new PopupMenu();

        // 创建菜单项
        MenuItem openItem = createMenuItem("打开程序", e -> showStage());

        MenuItem exitItem = createMenuItem("退出程序", e -> exitApp());

        // 设置全局字体
        Font chineseFont = new Font("Microsoft YaHei", Font.PLAIN, 12);
        menu.setFont(chineseFont);

        menu.add(openItem);
        menu.addSeparator();
        menu.add(exitItem);

        return menu;
    }

    private MenuItem createMenuItem(String text, ActionListener action) {
        MenuItem item = new MenuItem(text);
        item.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
        item.addActionListener(action);
        return item;
    }


    private JPopupMenu createJpopMenu() {
        jDialog = new JDialog();
        //关闭JDialog的装饰器
        jDialog.setUndecorated(true);
        //jDialog作为JPopupMenu载体不需要多大的size
        jDialog.setSize(1, 1);

        //创建JPopupMenu
        //重写firePopupMenuWillBecomeInvisible
        //消失后将绑定的组件一起消失
        jPopupMenu = new JPopupMenu() {
            @Override
            public void firePopupMenuWillBecomeInvisible() {
                jDialog.setVisible(false);
                System.out.println("JPopupMenu不可见时绑定载体组件jDialog也不可见");
            }
        };
        jPopupMenu.setSize(150, 30);

        // 使用Swing组件创建菜单项
        JMenuItem openItem = createJMenuItem("打开程序", e -> showStage());
        JMenuItem exitItem = createJMenuItem("退出程序", e -> exitApp());

        jPopupMenu.add(openItem);
        jPopupMenu.add(exitItem);

        return jPopupMenu;
    }

    private JMenuItem createJMenuItem(String text, ActionListener action) {
        JMenuItem jMenuItem = new JMenuItem(text);
        jMenuItem.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
        jMenuItem.addActionListener(action);
        return jMenuItem;
    }

    private Image createTrayImage(URL iconUrl) {
        try {
            return ImageIO.read(iconUrl.openStream());
        } catch (IOException e) {
            e.printStackTrace();
            return new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB);
        }
    }

    private void addTrayListeners() {
        trayIcon.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent e) {
                if (e.getClickCount() == 2) {
                    showStage();
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                //左键点击
                if (e.getButton() == 1) {
                    showStage();
                } else if (e.getButton() == 3 && e.isPopupTrigger()) {
                    if (jDialog == null || jPopupMenu == null) {
                        return;
                    }
                    // 右键点击弹出JPopupMenu绑定的载体以及JPopupMenu
                    jDialog.setLocation(e.getX() + 5, e.getY() - 5 - jPopupMenu.getHeight());
                    // 显示载体
                    jDialog.setVisible(true);
                    // 在载体的0,0处显示对话框
                    jPopupMenu.show(jDialog, 0, 0);
                }
            }
        });
    }

    private void showStage() {
        Platform.runLater(() -> {
            if (primaryStage.isIconified() || !primaryStage.isShowing()) {
                primaryStage.show();
                primaryStage.setIconified(false);
            }
        });
    }

    private void exitApp() {
        Platform.runLater(() -> {
            primaryStage.close();
            SystemTray.getSystemTray().remove(trayIcon);
            System.exit(0);
        });
    }
}

0

评论区