Roman Cs erste und akzeptierte Antwort wird nicht AUTO Schließen Sie das Menü mit untergeordneten MenuItems als Teil der JMenuBar.
Ausführen einer ((JMenu) e.getSource()). DoClick(); mousEntered simuliert den Klick in einen der JMenu-Eltern, kann aber nicht einfach zur mouseExited-Methode hinzugefügt werden, da der MouseListener sowohl an die untergeordneten MenuItems als auch an die JMenu-Eltern angehängt werden muss. (Was es in der normalen Zuordnung zur MenuBar nicht tut - nur an die übergeordneten JMenu-Objekte anfügen).
Außerdem tritt ein Problem auf, wenn versucht wird, den MouseExit-Listener dazu zu bringen, eine "close" -Methode auszulösen, NUR wenn die Maus die gesamte Menüstruktur verlassen hat (dh die Dropdown-Menüs untergeordnete Menüs).
Unten finden Sie eine voll funktionsfähige Antwort von meinem Live-App wurde:
So wie ich das Menü aus der Nähe auf der Maus gelöst war eine boolesche Variable „isMouseOut“ in der Spitze des Konstruktor zu laufen, um zu verfolgen , und weisen Sie dann den MouseListener einer OO-freundlicheren Weise zu, um die verschiedenen MouseIn-MouseOut-Ereignisse zu verfolgen, wenn ein Benutzer mit dem Menü interagiert. Dies ruft eine separate menuClear-Methode auf, die auf den Zustand des Boolean "isMouseOut" einwirkt. Die Klasse implementiert MouseListener. So ist es gemacht.
Erstellen Sie eine ArrayList, die zuerst alle Menüelemente zu diesem Array hinzufügt.Wie so:
Font menuFont = new Font("Arial", Font.PLAIN, 12);
JMenuBar menuBar = new JMenuBar();
getContentPane().add(menuBar, BorderLayout.NORTH);
// Array of MenuItems
ArrayList<JMenuItem> aMenuItms = new ArrayList<JMenuItem>();
JMenuItem mntmRefresh = new JMenuItem("Refresh");
JMenuItem mntmNew = new JMenuItem("New");
JMenuItem mntmNormal = new JMenuItem("Normal");
JMenuItem mntmMax = new JMenuItem("Max");
JMenuItem mntmStatus = new JMenuItem("Status");
JMenuItem mntmFeedback = new JMenuItem("Send Feedback");
JMenuItem mntmEtsyTWebsite = new JMenuItem("EtsyT website");
JMenuItem mntmAbout = new JMenuItem("About");
aMenuItms.add(mntmRefresh);
aMenuItms.add(mntmNew);
aMenuItms.add(mntmNormal);
aMenuItms.add(mntmMax);
aMenuItms.add(mntmStatus);
aMenuItms.add(mntmFeedback);
aMenuItms.add(mntmEtsyTWebsite);
aMenuItms.add(mntmAbout);
iteriert dann über die Arraylist in diesem Stadium ein Mouselistener Zugabe mit dem für() Schleife:
for (Component c : aMenuItms) {
if (c instanceof JMenuItem) {
c.addMouseListener(ml);
}
}
Nun setzen JMenu Eltern für das MenuBar:
// Now set JMenu parents on MenuBar
final JMenu mnFile = new JMenu("File");
menuBar.add(mnFile).setFont(menuFont);
final JMenu mnView = new JMenu("View");
menuBar.add(mnView).setFont(menuFont);
final JMenu mnHelp = new JMenu("Help");
menuBar.add(mnHelp).setFont(menuFont);
Fügen Sie dann die Dropdown-Menüelemente Kinder zu den JMenu-Eltern hinzu:
// Now set menuItems as children of JMenu parents
mnFile.add(mntmRefresh).setFont(menuFont);
mnFile.add(mntmNew).setFont(menuFont);
mnView.add(mntmNormal).setFont(menuFont);
mnView.add(mntmMax).setFont(menuFont);
mnHelp.add(mntmStatus).setFont(menuFont);
mnHelp.add(mntmFeedback).setFont(menuFont);
mnHelp.add(mntmEtsyTWebsite).setFont(menuFont);
mnHelp.add(mntmAbout).setFont(menuFont);
Fügen Sie die mouseListeners den JMenu Eltern als separater Schritt:
for (Component c : menuBar.getComponents()) {
if (c instanceof JMenu) {
c.addMouseListener(ml);
}
}
Jetzt, wo das Kind menuItem Elemente alle ihre eigenen Zuhörer haben, die den Elementen JMenu Eltern getrennt sind und die MenuBar selbst - Es ist wichtig zu erkennen der Objekttyp innerhalb der MouseListener() - Instantiierung, damit das Menü beim MouseOver automatisch geöffnet wird (in diesem Beispiel die 3x JMenu - Eltern) ABER AUCH vermeidet Kindausnahmefehler und erlaubt eine saubere Identifikation von mouseOUT der Menüstruktur ohne zu überwachen, wo Mausposition ist. Der Mouselistener ist wie folgt:
MouseListener ml = new MouseListener() {
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
isMouseOut = true;
timerMenuClear();
}
public void mouseEntered(MouseEvent e) {
isMouseOut = false;
Object eSource = e.getSource();
if(eSource == mnHelp || eSource == mnView || eSource == mnFile){
((JMenu) eSource).doClick();
}
}
};
Die oben simuliert nur die Maus in den (3x in diesem Beispiel) ‚Eltern‘ JMenu klicken, da sie die Auslöser für die untergeordnete Menü-Dropdown-Listen sind. Die timerMenuClear() -Methode ruft den MenuSelectionManager zum Zeitpunkt der realen mouseOut Live was auch immer SelectedPath Punkt zu leer war:
public void timerMenuClear(){
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(isMouseOut == true){
System.out.println("Timer");
MenuSelectionManager.defaultManager().clearSelectedPath();
}
}
};
//Delay timer half a second to ensure real mouseOUT
Timer timer = new Timer(1000, task);
timer.setInitialDelay(500);
timer.setRepeats(false);
timer.start();
}
Es hat mir eine wenig Prüfung, Überwachung, welche Werte ich in der JVM während seiner Entwicklung zugreifen konnte - aber es funktioniert ein Vergnügen! sogar mit verschachtelten Menüs :) Ich hoffe, dass viele dieses vollständige Beispiel sehr nützlich finden.
Haben Sie einen guten Grund, warum Sie das tun möchten? Alle Menüleisten in allen Anwendungen verhalten sich so – Robin
Gut mein Menü hat ein kundenspezifisches Aussehen und dieses Verhalten passt es natürlicher. Außerdem glaube ich, dass dieses Verhalten für den Benutzer viel interaktiver ist. – springcorn