# JComboBox automatisch zuklappen



## ulim (4. Mai 2011)

Hallo allerseits,

ich habe das schon in anderen Foren gefragt, aber keiner wusste bisher eine Lösung.

Ich möchte eine JComboBox bauen, die ihr PopupMenu automatisch aufklappt, wenn man mit dem Mauszeiger draufkommt (kein Problem) und automatisch wieder zuklappt, wenn man mit dem Mauszeiger das PopupMenu wieder verlässt (das ist das Problem).

Ersteres ließ sich mit einem MouseListener lösen, den ich auf alle Elemente (Items) des PopupMenus setzte. Bei mouseEntered() öffne ich dann das Popup mit showPopup(), wenn es noch nicht offen ist. Das mouseExited() Event kommt dann allerdings auch bei jedem Element, das man verlässt, also auch dann, wenn man nur durch die Liste der Items scrollt. Ich kann diesen Umstand dann nicht mehr unterscheiden von dem, dass das PopupMenu komplett verlassen wird - und nur da möchte ich hidePopup() aufrufen.

Mit einem FocusListener kam ich auch nicht weiter, da der Fokus erst verloren geht, wenn man neben der JComboBox ins Fenster klickt - dann aber geht das PopupMenu sowieso zu. Ich möchte aber, dass es schon zu geht, wenn nur der Mauszeiger es verlässt.

Ein Experte, den ich fragte, meinte ich müsse irgendwie an die UIResource ran. Damit meinte er wohl die DefaultComboBoxUI oder? Dort konnte ich aber auch keine Stelle finden, wo ich mich einklinken könnte.

Hat irgendjemand vielleicht eine Idee was man noch probieren könnte?

Ulrich


----------



## Michael... (4. Mai 2011)

Ich würde mich da grundsätzlich fragen, ob das dann überhaupt eine ComboBox ist oder nicht einfach "nur" ein JPopupMenu mit einer JList, das über/unter einen JLabel/JTextField erscheint und bei einer Selektion oder einem mouseExited das Menüs wieder verschwindet.


----------



## ulim (5. Mai 2011)

Könnte man natürlich machen, allerdings sollte das Ganze im zugeklappten Zustand optisch schon wie eine ComboBox aussehen, ein einfaches Textfield zeigt dem Benutzer ja nicht, dass er dort etwas ausfüllen kann. Ein Button wäre wohl auch nicht das richtige... 

Ulrich


----------



## Michael... (5. Mai 2011)

Wenn man das auf Basis einer JComboBox müsste man schauen, ob man irgendwie auf deren JPopupMenu Zugriff bekommt.

Grundsätzlich wird - wie von Deinem Experten erwähnt - Aussehen und Verhalten durch das verwendete LaF bestimmt. Wenn Dir das LaF egal ist, kann man ein UI selbst definieren, siehe ComboBoxUI, BasicComboBoxUI usw.


----------



## ulim (5. Mai 2011)

In diesem Fall und nur für das Verhalten dieser Komponente ist das L&F mir egal, das Teil soll immer genauso funktionieren, das hat einen bestimmten Sinn. Was diese UIResources etc. angeht bin ich allerdings am Ende meiner Kompetenz angelangt, von daher überlege ich, ob ich nicht doch Deine erste Idee aufgreifen sollte und statt des Labels einfach einen Screenshot einer zugeklappten Combobox nehme, so dass es zumindest so aussieht.

Ulrich


----------



## Michael... (5. Mai 2011)

ulim hat gesagt.:


> von daher überlege ich, ob ich nicht doch Deine erste Idee aufgreifen sollte und statt des Labels einfach einen Screenshot einer zugeklappten Combobox nehme, so dass es zumindest so aussieht.


Anstelle des "statischen" Screenshots könnte man auch eine JComboBox auf das Label (wobei ich dann eher eine JComponent nehmen würde) zeichnen lassen. Dann passt das Aussehen auch immer zum LaF des Users  ;-)


----------



## ulim (5. Mai 2011)

Das hört sich ja spannend an, wie geht denn sowas? Eine JComboBox auf eine JComponent zeichnen lassen?!?

Ulrich


----------



## ulim (6. Mai 2011)

Schlimm, aber es funktioniert:


```
public class MyComboBox extends JComboBox {
            ...
            java.lang.reflect.Field popupInBasicComboBoxUI = BasicComboBoxUI.class.getDeclaredField("popup");
            popupInBasicComboBoxUI.setAccessible(true);
            BasicComboPopup popup = (BasicComboPopup) popupInBasicComboBoxUI.get(getUI());
            Field scrollerInBasicComboPopup = BasicComboPopup.class.getDeclaredField("scroller");
            scrollerInBasicComboPopup.setAccessible(true);
            JScrollPane scroller = (JScrollPane) scrollerInBasicComboPopup.get(popup);
            scroller.getViewport().getView().addMouseListener(new MouseAdapter() {
                @Override public void mouseExited(MouseEvent e) {
                    if (isPopupVisible()) {
                        hidePopup();
                    }
                }
            });
```


----------

