首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自动隐藏JMenuBar

自动隐藏JMenuBar
EN

Stack Overflow用户
提问于 2010-05-26 18:02:05
回答 4查看 7.8K关注 0票数 5

当我运行下面的代码时,当光标移动到窗口的上半部分时,菜单栏显示。问题是,当我向上移动光标打开菜单,但没有选择任何内容,然后将光标移出菜单栏区域时,它变得不可见,但菜单的元素留在屏幕上。

我试图实现的是一个“自动隐藏”菜单栏,当鼠标进入JFrame中的某个区域时,它就会变得可见。

代码语言:javascript
复制
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);
    }
}

我想我找到了一种解决方法:如果菜单栏可见,并且JFrame接收到鼠标移动事件,则发送ESC键来关闭任何打开的菜单。

代码语言:javascript
复制
 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);
            }
        });

此解决方法取决于外观( ESC键的含义)。无论如何,对我来说,这是可以的。

EN

回答 4

Stack Overflow用户

发布于 2010-05-26 20:39:16

您可能可以通过检查是否从JMenuBar中选择了任何菜单来使其正常工作:

代码语言:javascript
复制
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);
}

在这种情况下,只要您单击JFrame中的其他位置,它就会消失。

然而,并不完全是这样,因为它只会在mouseMoved上更新。我建议你在mouseClicked上做同样的检查,以确保在不移动的情况下单击时它会消失。

票数 2
EN

Stack Overflow用户

发布于 2012-10-30 01:29:40

同样有效:

代码语言:javascript
复制
frame.addMouseMotionListener(new MouseAdapter() {
        @Override
        public void mouseMoved(MouseEvent e) {
            if (menuBar.isSelected()) {
                try {
                    Robot robot = new Robot();
                    robot.keyPress(KeyEvent.VK_ESCAPE);
                    SingleSelectionModel sm = menuBar.getSelectionModel();
                    sm.clearSelection();
                } catch (AWTException ex) {
                }

            }
        }
    });
票数 2
EN

Stack Overflow用户

发布于 2015-01-02 09:34:34

您还可以在窗口中添加一个透明面板区域,并将一个单独的MouseListener附加到该区域面板上,这样您就可以显示一个不可见的菜单!但是这个想法并没有包含在我的例子中。

下面的是一个完全可用的AutoHide分层MenuBar,取自我的实时应用程序:

我解决鼠标输出时菜单关闭的方法是在构造函数的顶部运行一个布尔变量"isMouseOut“来跟踪,然后以一种更面向对象的方式分配MouseListener,以便在用户与菜单交互时跟踪多个鼠标输入-鼠标输出事件。它调用作用于布尔值"isMouseOut“的状态的单独的menuClear方法。该类实现了MouseListener。这就是它是如何完成的。

创建一个ArrayList,首先将所有菜单项添加到此数组中。如下所示:

代码语言:javascript
复制
    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);

然后在此阶段迭代arrayList,使用for()循环添加一个MouseListener:

代码语言:javascript
复制
  for (Component c : aMenuItms) {
        if (c instanceof JMenuItem) {
            c.addMouseListener(ml);
        }
    }

现在为MenuBar设置JMenu父对象:

代码语言:javascript
复制
// 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);

然后将dropdown menuItems子项添加到JMenu父项:

代码语言:javascript
复制
// 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);

将mouseListeners作为单独的步骤添加到JMenu父项:

代码语言:javascript
复制
    for (Component c : menuBar.getComponents()) {
        if (c instanceof JMenu) {
            c.addMouseListener(ml);
        }
    }

既然子menuItem元素都有自己的侦听器,这些侦听器独立于父JMenu元素和MenuBar本身-在MouseListener()实例化中标识对象类型是很重要的,这样您就可以在鼠标悬停时自动打开菜单(在本例中是3倍的JMenu父元素),但也避免了子异常错误,并且允许清晰地标识菜单结构的mouseOUT,而不需要尝试监控鼠标的位置。MouseListener如下:

代码语言:javascript
复制
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();
            }
        }
    }; 

上面只模拟了鼠标点击进入JMenu 'parents‘(在本例中是3倍),因为它们是子菜单下拉菜单的触发器。timerMenuClear()方法在MenuSelectionManager上调用,以清空在实际mouseOUT时活动的所选路径点:

代码语言:javascript
复制
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();
}

我花了一些时间进行测试,监视在JVM开发期间我可以在JVM中访问哪些值--但它的效果非常好!即使是嵌套菜单:)我希望很多人会发现这个完整的例子非常有用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2911887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档