Auto-hide JMenuBar

PeterMmm picture PeterMmm · May 26, 2010 · Viewed 7.6k times · Source

When I run the following code, the menu bar shows when the cursor moves to the upper part of the window. The problem is, when I move the cursor up to open the menu but do not select anything, and then move the cursor out of the the menu bar area, it becomes invisible but the menu's elements stay on screen.

What I'm try to achieve is an "auto-hide" menu bar that becomes visible when the mouse enters a certain region in the JFrame.

public class Test extends JFrame {

    public Test() {
        setLayout(new BorderLayout());
        setSize(300, 300);

        JMenuBar mb = new JMenuBar();
        setJMenuBar(mb);
        mb.setVisible(false);


        JMenu menu = new JMenu("File");
        mb.add(menu);

        menu.add(new JMenuItem("Item-1"));
        menu.add(new JMenuItem("Item-2"));

        addMouseMotionListener(new MouseAdapter() {

            @Override
            public void mouseMoved(MouseEvent e) {
                getJMenuBar().setVisible(e.getY() < 50);
            }
        });
    }

    public static void main(String args[]) {
        new Test().setVisible(true);
    }
}

I think I found a workaround: if the menu bar is visible and the JFrame receives a mousemove event then send the ESC key to close any open menu.

 addMouseMotionListener(new MouseAdapter() {

            @Override
            public void mouseMoved(MouseEvent e) {
                if (getJMenuBar().isVisible()) {
                    try {
                        Robot robot = new Robot();
                        robot.keyPress(KeyEvent.VK_ESCAPE);
                    } catch (AWTException ex) {
                    }

                }
                getJMenuBar().setVisible(e.getY() < 50);
            }
        });

This workaround depends on the look and feel (meaning of the ESC key). Anyway, for me it is ok.

Answer

Gnoupi picture Gnoupi · May 26, 2010

You can probably make it work by checking is any menu is selected, from the JMenuBar:

public void mouseMoved(MouseEvent e) {
    JMenuBar lMenu = getJMenuBar();
    boolean hasSelectedMenu = false;
    for (int i=0 ; i< lMenu.getMenuCount() ; ++i)
    {
        if (lMenu.getMenu(i).isSelected())
        {
            hasSelectedMenu = true;
            break;
        }
    }

    if(!hasSelectedMenu)
        lMenu.setVisible(e.getY() < 50);
}

In this case, it would disappear as soon as you click somewhere else in the JFrame.

However, not exactly, as it would update only on mouseMoved. I would recommend you to do the same check on mouseClicked, to be sure it disappears when clicking without moving.