这个问题与这个问题类似。我所拥有的是JPopupMenu
从系统托盘上的图标弹出的。此时,系统托盘是程序的唯一体现。也就是说,没有其他窗口打开,系统托盘中的图标是我访问该程序的唯一途径。我JPopupMenu
在 AWT 上使用 a 是PopupMenu
因为我想将系统外观应用到弹出菜单 - 当我只使用一个普通的时PopupMenu
,我无法获得系统的外观和感觉,我只是不断地获得 Swing 的金属外观。我使用此解决方法来获得此行为(在此处描述):
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());
systemTrayPopupMenu.setInvoker(systemTrayPopupMenu);
systemTrayPopupMenu.setVisible(true);
}
}
};
当我右键单击托盘图标时,它会显示菜单,当我进行选择时,菜单自然会消失。但是,当我调出菜单然后单击它时,它并没有消失。要使其当前消失,我必须进行选择,或者选择已禁用的菜单项之一。
我尝试向其中添加 a FocusListener
,但是,没有迹象表明focusLost
orfocusGained
方法曾经被调用过。此外,当另一个获得焦点时,我不能让它消失,Window
因为没有其他窗口存在。由于此弹出菜单来自 aTrayIcon
而不是典型按钮,因此我无法使用此处提到的解决方案来解决FocusListener
not calling focusLost
。
最终,我想知道的是: 1
)有没有办法让系统的外观和感觉适合正常的 AWT PopupMenu
?,或者
2)有没有办法JPopupMenu
在失去焦点时让它消失?
编辑:根据要求,这是我的SSCCE
:
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 {
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;
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());
systemTrayPopupMenu.setInvoker(systemTrayPopupMenu);
systemTrayPopupMenu.setVisible(true);
}
}
});
try {
systemTray.add(trayIcon);
} catch (AWTException e) {
System.out.println("Could not place item at tray. Exiting.");
}
}
}
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) {
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();
menu.add(item);
item.addActionListener(listener);
}
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));
}
}