Этот вопрос похож на this one. У меня есть JPopupMenu
, который появляется из значка на панели задач. На этом этапе системный лоток является единственным проявлением программы. То есть других открытых окон нет, значок в системном трее - единственный способ получить доступ к программе. Я использовал по AWT PopupMenu
, потому что я хотел получить систему Look and Feel, примененную к всплывающему меню - когда я использовал просто равную PopupMenu
, я не мог получить Look and Feel системы, я просто продолжал получать Metal Look Look и Swing Чувствовать. Я использовал эту работу вокруг, чтобы получить такое поведение (описано here):Не удается скрыть SystemTray JPopupMenu, когда он теряет фокус
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);
}
}
};
Когда я правой кнопкой мыши на иконке в трее, он показывает меню, и, естественно, когда я делаю выбор, меню исчезает. Однако, когда я поднимаю меню, а затем выхожу из него, он не исчезает. Чтобы это исчезло в настоящее время, я должен либо сделать выбор, либо выбрать один из пунктов меню, которые отключены.
Я попытался добавить к нему FocusListener
, однако нет никаких указаний на то, что вызовы вызвали методы focusLost
или focusGained
. Кроме того, я не могу заставить его исчезнуть, когда другой Window
получает фокус, потому что других окон нет. Поскольку это всплывающее меню происходит от TrayIcon
, а не типичной кнопки, я не могу использовать упомянутое решение here, чтобы обойти FocusListener
, не вызывая focusLost
.
В конце концов, то, что я интересно либо:
1) Есть ли способ, чтобы получить вид системы и чувствовать себя для нормального AWT PopupMenu
или
2) Есть ли способ сделать JPopupMenu
? исчезают, когда он теряет фокус?
EDIT: По желанию, вот мой 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));
}
}
. Это на самом деле проблема для многих значков лотков ... поскольку у них нет концепции родительского фокуса, чтобы знать, когда фокус действительно изменился. Лучшее решение, которое я видел, - просто разместить «закрытую» опцию в конце меню и заставить пользователя закрыть его;) Я не пробовал, но я подумал о добавлении привязки клавиш к экрану эвакуации ... – MadProgrammer
Опубликуйте свой 'SSCCE', который демонстрирует проблему. – camickr