The initial and accepted answer of Roman C will not be AUTO. Close the menu with the child MenuItems as part of the JMenuBar.
Running a ((JMenu) e.getSource ()). doClick (); on mouseEntered imitates a click on one of the JMenu parents, but cannot be simply added to the mouseExited method, since the MouseListener needs to be attached to the child MenuItems, as well as to the JMenu parents. (Which it does not perform in the usual way in MenuBar - only for connecting to JMenu's parent objects).
In addition, there is a problem associated with trying to force the MouseExit listener to run the "private" method ONLY when the mouse leaves the entire menu structure (i.e., the Child drop-down menus).
Below is the full working answer from my application:
The way I decided to close the menu was to run the “isMouseOut” boolean at the top of the constructor for tracking, and then allocate MouseListener in a more convenient way for OO to track multiple MouseIn Events —MouseOut as the user interacts with the menu. Which calls a separate menuClear method that acts on the state of the logical "isMouseOut". The class implements MouseListener. Here's how to do it.
Create an ArrayList by first adding all the menu items to this array. For example:
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);
then go through the list array at this point by adding a MouseListener using a for () loop:
for (Component c : aMenuItms) { if (c instanceof JMenuItem) { c.addMouseListener(ml); } }
Now set the JMenu parents for the 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);
Then add the Children items drop-down menu to JMenu's parents:
// 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);
Add mouseListeners to JMenu parents as a separate step:
for (Component c : menuBar.getComponents()) { if (c instanceof JMenu) { c.addMouseListener(ml); } }
Now that the elements of the childEtem element have their own listeners, which are separate for the parent elements of JMenu and the MenuBar itself, it is important to identify the type of the object in the MouseListener () instance so that you automatically open the mouseover menu (in this example, 3x of the JMenu parent), BUT ALSO avoids the errors of child exceptions and allows you to clear the mouseout identification of the menu structure without trying to control where the mouse position is. MouseListener looks like this:
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(); } } };
The above only simulates a mouse click on JMenu's parents (3x in this example), as they are triggers for the drop-down menus of the child menu. The timerMenuClear () method calls MenuSelectionManager in order to empty any selected waypoint in real time at the time of the real mouse:
public void timerMenuClear(){ ActionListener task = new ActionListener() { public void actionPerformed(ActionEvent e) { if(isMouseOut == true){ System.out.println("Timer"); MenuSelectionManager.defaultManager().clearSelectedPath(); } } };
It took me a bit of testing, keeping track of what values I could get in the JVM during its development, but it works! even with nested menus :) I hope many find this complete example very useful.