JAVA Swing 系统托盘菜单实现 JPopupMenu + JDialog 取代 PopupMenu

PopupMenu

中文乱码,还不支持UTF-8单调,没法添加骚气的图片

JPopupMenu

必须选择某项才消失,点击屏幕任何地放不会消失

思路

JPopupMenu 绑定到一个Component组件上(使用setInvoker / show),此时点击屏幕任何地方都会消失,JPopupMenu不可见时设置绑定的Component组件也不可见

尝试

JPopupMenu + JFrame
JPopupMenu + JWindow
JPopupMenu + JDialog
最终方案
JPopupMenu + JDialog

package com.genscript.print.dto;

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.*;

public class SwingSystemTray {

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run () {
            try {
                /* We are going for the Windows Look and Feel here */
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                new SwingSystemTray ();
            } catch (Exception e) {
                System.out.println("Not using the System UI defeats the purpose...");
                e.printStackTrace();
            }
        }
    });
}

protected SystemTray systemTray;
protected TrayIcon trayIcon;
protected JPopupMenu systemTrayPopupMenu;
protected Image iconImage;
/* Added a "hidden dialog" */
protected JDialog hiddenDialog;

public SwingSystemTray () throws IOException {
    iconImage = getIcon ();
    if (SystemTray.isSupported()) {
        systemTray = SystemTray.getSystemTray();
        systemTrayPopupMenu = buildSystemTrayJPopupMenu();
        trayIcon = new TrayIcon(iconImage, "Application Name", null /* Popup Menu */);
        trayIcon.addMouseListener (new MouseAdapter () {
            @Override
            public void mouseReleased (MouseEvent me) {
                if (me.isPopupTrigger()) {
                    systemTrayPopupMenu.setLocation(me.getX(), me.getY());
                    /* Place the hidden dialog at the same location */
                    hiddenDialog.setLocation(me.getX(), me.getY());
                    /* Now the popup menu's invoker is the hidden dialog */
                    systemTrayPopupMenu.setInvoker(hiddenDialog);
                    hiddenDialog.setVisible(true);
                    systemTrayPopupMenu.setVisible(true);
                }
            }
        });
        trayIcon.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed (ActionEvent ae) {
                System.out.println("actionPerformed");
            }
        });
        try {
            systemTray.add(trayIcon);
        } catch (AWTException e) {
            System.out.println("Could not place item at tray.  Exiting.");
        }
    }
    /* Initialize the hidden dialog as a headless, titleless dialog window */
    hiddenDialog = new JDialog ();
    hiddenDialog.setSize(10, 10);
    /* Add the window focus listener to the hidden dialog */
    hiddenDialog.addWindowFocusListener(new WindowFocusListener () {
        @Override
        public void windowLostFocus (WindowEvent we ) {
            hiddenDialog.setVisible(false);
        }
        @Override
        public void windowGainedFocus (WindowEvent we) {}
    });
}

protected JPopupMenu buildSystemTrayJPopupMenu () {
    final JPopupMenu menu = new JPopupMenu ();
    final JMenuItem showMenuItem = new JMenuItem("Show");
    final JMenuItem hideMenuItem = new JMenuItem("Hide");
    final JMenuItem exitMenuItem = new JMenuItem("Exit");
    hideMenuItem.setEnabled(false);
    ActionListener listener = new ActionListener () {
        @Override
        public void actionPerformed (ActionEvent ae) {
            /* We want to make sure the hidden dialog goes away after selection */
            hiddenDialog.setVisible(false);
            Object source = ae.getSource();
            if (source == showMenuItem) {
                System.out.println("Shown");
                showMenuItem.setEnabled(false);
                hideMenuItem.setEnabled(true);
            }
            else if (source == hideMenuItem) {
                System.out.println("Hidden");
                hideMenuItem.setEnabled(false);
                showMenuItem.setEnabled(true);
            }
            else if (source == exitMenuItem) {
                System.exit(0);
            }
        }
    };
    for (JMenuItem item : new JMenuItem [] {showMenuItem, hideMenuItem, exitMenuItem}) {
        if (item == exitMenuItem) {
            menu.addSeparator();
        }
        item.addActionListener(listener);
        menu.add(item);
    }
    return menu;
}

protected Image getIcon () throws IOException {
    // Build the 16x16 image programmatically, start with BMP Header
    byte [] iconData = new byte[822];
    System.arraycopy(new byte [] {0x42,0x4d,0x36,0x03, 0,0,0,0, 0,0,0x36,0,
            0,0,0x28,0, 0,0,16,0, 0,0,16,0, 0,0,16,0, 24,0,0,0, 0,0,0,3},
            0, iconData, 0, 36);
    for (int i = 36; i < 822; iconData[i++] = 0);
    for (int i = 56; i < 822; i += 3) iconData[i] = -1;
    return ImageIO.read(new java.io.ByteArrayInputStream(iconData));
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值