J'ai créé une application Java Swing qui n'a aucune fenêtre principale visible mais qui est contrôlée à travers son icône de plateau en cliquant avec le bouton droit de la souris. P>
J'utilise un À l'origine, j'utilisais un menu contextuel qui fonctionnait comme prévu, mais cela ne m'a pas permis d'avoir des icônes dans le menu. P>
Comment puis-je le faire fermer lorsque je clique ailleurs, comme prévu? P> jpopupmenu code> pour cela, mais lorsque je clique à l'extérieur du menu contextuel (par exemple, dans la fenêtre d'une autre application ou sur le bureau), le JPOPUPMENU code> ne disparaît pas. n'est pas le comportement attendu. P>
4 Réponses :
Il y a des bugs lorsque vous utilisez JPOPUPMEN: JTRAYICON: Swing Swing JPOPUPMENUS pour le plateau Icônes . Près de la fin est un lien vers une solution possible. Je n'ai pas essayé donc je ne sais pas si cela réparera votre problème ou non. P>
à la fin je "résolue" cela en piratant autour de la question. Comme le souligne Camickr, JPopupMenu est assez buggy. Cependant, c'est la seule implémentation du menu contextuel de balançoire qui vous permet d'avoir une icône à côté de chaque élément de menu. P>
Ma solution consistait à mettre en place un auditeur sur le JPopupmenu qui, si l'utilisateur placait la souris sur le menu, après 3 secondes, il serait défini sur .isvissible (FALSE) Si l'utilisateur n'a pas mis la souris sur le menu. Dans ce temps. P>
Pour y parvenir, je devais utiliser un fil séparé qui vérifiait constamment si le popupmenu était actif. Si tel est le cas, vérifiez si la souris était sur elle, à l'aide d'un auditeur d'événements et définissez la visibilité sur FALSE si l'utilisateur ne l'ait pas revenu dans les 3 secondes. P>
Ce n'est pas une solution parfaite car l'utilisateur doit toujours attendre 3 secondes pour que le menu disparaisse (il devrait être instantané s'il clique) et il disparaîtra même s'il est en train de se concentrer (il ne devrait pas si l'utilisateur clique sur). Cependant, il se sentait «assez bon» d'être accepté. P>
espère que cela aide. p>
//_Popup is your JPopupMenu, call this method before setting your popup to visible
public void armPopup()
{
if(_Popup != null)
{
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener()
{
@Override
public void eventDispatched(AWTEvent event) {
if(event instanceof MouseEvent)
{
MouseEvent m = (MouseEvent)event;
if(m.getID() == MouseEvent.MOUSE_CLICKED)
{
_Popup.setVisible(false);
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
}
}
if(event instanceof WindowEvent)
{
WindowEvent we = (WindowEvent)event;
if(we.getID() == WindowEvent.WINDOW_DEACTIVATED || we.getID() == WindowEvent.WINDOW_STATE_CHANGED)
{
_Popup.setVisible(false);
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
}
}
}
}, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK);
}
}
Cela fonctionne bien sur Windows 10 si le système d'exploitation le place directement sur la partie visible du plateau, mais échoue si l'OS place l'icône dans un "sous-plateau pliable" ou de ce que ce panneau est appelé.
J'étais récemment stratifié avec cette "vieille" problème. Voici ma solution qui fonctionne bien et à mes attentes.
J'ai ajouté une fenêtre transparente non décorée dans la classe d'icônes du plateau et jointe à un focallistener. Lorsque la popup est déclenchée pour être affichée, l'événement de la souris déclenche également la fenêtre transparente à afficher (qui ne peut pas être vu en raison de sa transparence). La fenêtre obtient un événement gagné. Lorsque la souris est cliquée quelque part sur l'écran en dehors de la popup, il déclenche l'événement Focuslost de la fenêtre transparente. Cet événement est maintenant utilisé pour définir la popup to invisible. P>
public MyTrayIconApp() {
if (!SystemTray.isSupported()) {
System.out.println("SystemTray is not supported");
System.exit(0);
}
// work around to close popup if mouse is clicked outside of popup
transparentWindow = new JFrame();
transparentWindow.setType(JFrame.Type.UTILITY); // avoid task bar icon
transparentWindow.setUndecorated(true);
transparentWindow.setOpacity(0.0f);
transparentWindow.addFocusListener(new FocusListener(){
@Override
public void focusGained(FocusEvent e) {}
@Override
public void focusLost(FocusEvent e) {
if (popup.isVisible())
popup.setVisible(false);
transparentWindow.dispose();
}
});
popup = new JPopupMenu();
icon = new ImageIcon(IndexWatcherTrayIcon.class.getResource("/16x16/myIcon.png"));
trayIcon = new TrayIcon(icon);
tray = SystemTray.getSystemTray();
// Create pop-up menu components
JMenuItem startstopItem = new JMenuItem("Stop");
JMenuItem updateItem = new JMenuItem("Update Indexes");
JMenuItem exitItem = new JMenuItem("Exit");
// Add components to pop-up menu
popup.add(startstopItem);
popup.add(updateItem);
popup.addSeparator();
popup.add(exitItem);
// Add mouse listener to tray icon
trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
transparentWindow.setVisible(true);
popup.setLocation(e.getX(), e.getY());
popup.setInvoker(popup);
popup.setVisible(true);
}
}
});
// Add tray icon to system tray
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.out.println("TrayIcon could not be added.");
}
}