# Workaround: TrayIcon & JPopupMenu



## hdi (8. Jan 2011)

Hey,

ich habe in meiner Applikation ein TrayIcon, welches von Haus aus eine setPopupMenu(PopupMenu) Methode anbietet. Leider ist das AWT, und in der API wird auch davon geredet dass Swing da nicht unterstützt ist. Da mir AWT aber nicht gefällt und ich unbedingt ein *J*PopupMenu wollte habe ich das kurzerhand so hingebogen. Ich ignoriere diese Popup-Funktionalität des TrayIcon einfach (setPopupMenu(null)) und manage selber ein JPopupMenu mit nem MouseListener auf dem TrayIcon.

Es funktioniert nun nach etwas Rumprobieren auch, das Dumme nur: Ich weiß nicht warum  Und es ist kein gutes Gefühl Code zu haben, der zwar (scheinbar) funktioniert, ohne dass man jedoch versteht was der Code eigentlich tut  Ich hoffe jemand hat gerade etwas Interesse sich mit dem Code zu beschäftigen  (Ist nicht viel)

Also: MouseListener auf meinem TrayIcon, bei mousePressed zeige ich mein JPopupMenu an. Erster Versuch sah so aus:


```
@Override
	public void mousePressed(MouseEvent e) {
		popup.show(null, e.getX(), e.getY());
	}
```

Die show-Methode erwartet als ersten Parameter eine Component - es hat sich herausgestellt dass wenn man null übergibt (oder diese Methode ganz meidet und per setLocation & setVisible arbeitet) nicht die typische Popup-Menu Funktionalität vorhanden ist. D.h.: Wenn man mit der Maus über die MenuItems geht, ändert sich daran nix. Normalerweise werden die dann ja farblich unterlegt. Also das hat mir nicht gefallen denn das sieht irgendwo so aus als sei das Programm abgestürzt (das ist es nicht). Außerdem verschwindet das Popup nicht wenn man woanders hinklickt.

Also dachte ich mir okay ich brauche also eine Component statt dem null. Zuerst einmal einfach new JFrame() übergeben, aber das führt zu ner Exception: Die Component muss gerade visible sein.
Okay also hab ich mir nen Dummy-Dialog gebastelt:


```
popupDummy = new JDialog();
		popupDummy.setSize(0, 0);
		popupDummy.setUndecorated(true);
                popupDummy.setVisible(true);
```

und die show() angepasst:



```
@Override
	public void mousePressed(MouseEvent e) {
		popup.show(popupDummy, e.getX(), e.getY());
	}
```

Hurra, jetzt tut sich was beim Mouse-Over, also das passt. Aber das Problem mit dem Nicht-Verschwinden beim Klick woanders hin ist noch immer da. 

Und jetzt kommt das, was ich nicht verstehe: Ich hab dann mal einfach aus Gaudi das setVisible(true) für den Dummy-Dialog mit in diese Methode reingenommen:


```
@Override
	public void mousePressed(MouseEvent e) { 
                popupDummy.setVisible(true);
		popup.show(popupDummy, e.getX(), e.getY());
	}
```

Voila: Wenn man jetzt bei angezeigtem Popup irgendwo außerhalb des Popups klickt verschwindet es. *WARUM? * Ich check's nicht, ein setVisible(false) o.ä. mach ich nicht - das hier ist wirklich der gesamte Code dafür! Ich hab mal gekuckt ob ein popupDummy.requestFocus() auch ausreicht, tut's aber nicht. Also was passiert beim setVisible(true) noch, dass er komischerweise das Popup verschwinden lässt wenn man woanders hinklickt. Was hat das damit zu tun? Immerhin kommt das setVisible ja BEVOR ich die show() Methode aufrufe, die ja nach dem ersten mal sowieso nix mehr ändert weil der Dummy dann schon visible ist.

Wer mir das erklären kann dem bin ich sehr dankbar! 

Und jetzt noch ne Kleinigkeit, wer ne Idee hat: Wie bekomm ich ein "AlwaysOnTop"-Verhalten auf mein JPopupMenu?

lg


----------



## Wildcard (8. Jan 2011)

Es geht doch nur um ein Popup nicht um aufwendigen GUI Code, also warum nicht einfach AWT benutzen wie es in der API vorgesehen ist?


----------



## Illuvatar (8. Jan 2011)

Vielleicht hilft dir auch das?
JTrayIcon update | Java.net
https://swinghelper.dev.java.net/source/browse/swinghelper/src/java/org/jdesktop/swinghelper/tray/JXTrayIcon.java?view=markup
Das klingt doch eigentlich, als ob es gut funktionieren sollte... aber es  wird ziemlich ähnlich gemacht wie bei dir. _Warum_ man das jetzt genau so machen soll, steht da natürlich leider auch nicht...


----------



## Runtime (9. Jan 2011)

Wildcard hat gesagt.:


> Es geht doch nur um ein Popup nicht um aufwendigen GUI Code, also warum nicht einfach AWT benutzen wie es in der API vorgesehen ist?



Unter einigen Betriebssystemen geht das PopupMenu von AWT nicht zu, wenn es den Fokus verliert.


----------

