如何通过单击外部来关闭JPopupMenu时阻止触发其他事件?

时间:2011-06-03 17:14:32

标签: java swing menu jpopupmenu

我想用JPopupMenu复制右键单击上下文菜单的一些属性:

  1. 当菜单打开并点击其他地方时,菜单关闭。
  2. 当菜单打开并且您点击其他地方时,没有其他任何事情发生。
  3. 我的第一部分很好。但是当我点击其他地方时,可能会发生其他事件。例如,假设我有按钮A,它执行一些操作,B。目前,如果JPopupMenu打开,并且我单击A,则JPopupMenu关闭并执行B.我希望JPopupMenu关闭,B不要执行。这可能吗?

    由于

2 个答案:

答案 0 :(得分:11)

这很有效,而且简单得多......虽然可以被一些外观所覆盖。

UIManager.put("PopupMenu.consumeEventOnClose", Boolean.TRUE);

值得注意的是,这仅消耗MOUSE_PRESSED事件,不会消耗后续的MOUSE_CLICKED事件。您可以通过在mousePressed()中设置标志并在mouseReleased()中测试它来模拟鼠标单击。如果消耗了初始鼠标,则不会在mouseReleased()

中设置该标志
private boolean pressed = false;

@Override
public void mousePressed(MouseEvent e) {
    pressed = true;
}

@Override
public void mouseReleased(MouseEvent e) {
    if (pressed) {
         // do click stuff
    }
    pressed = false;
}

答案 1 :(得分:3)

考虑到您的问题和评论中的内容,我会通过以下方式之一解决您的问题。

从技术上讲,你有两个选择:

1.只要用户将鼠标移到弹出窗口之外,就会隐藏弹出窗口。这样您就不会遇到用户点击的问题,因为弹出窗口会自动消失。

2.全局捕获此特定鼠标事件,如果弹出窗口可见,则在左键单击时使用该事件。我在下面的例子中展示了这个特殊的解决方案。

    import java.awt.AWTEvent;
    import java.awt.Toolkit;
    import java.awt.event.AWTEventListener;
    import java.awt.event.ActionEvent;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import javax.swing.AbstractAction;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JPanel;
    import javax.swing.JPopupMenu;
    import javax.swing.SwingUtilities;

    public class DisableClickWhenPopupVisibleTest
    {
        public static void main(String[] args)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                @Override
                public void run()
                {               
                    final JPopupMenu popup = new JPopupMenu();
                    popup.add(new JMenu("aAaa"));
                    JPanel contentPane = new JPanel();
                    contentPane.add(popup);
                    JButton b = new JButton();
                    b.setAction(new AbstractAction("Button")
                    {
                        private static final long serialVersionUID = 1L;
                        @Override
                        public void actionPerformed(ActionEvent e)
                        {
                            System.out.println("b actionPerformed");
                        }
                    });
                    contentPane.add(b);
                    contentPane.addMouseListener(new MouseAdapter() {
                        @Override
                        public void mousePressed(MouseEvent e)
                        {
                            showPopup(e);
                        }
                        @Override
                        public void mouseReleased(MouseEvent e)
                        {
                            showPopup(e);
                        }
                        private void showPopup(MouseEvent e)
                        {
                            if(e.isPopupTrigger())
                                popup.show(e.getComponent(), e.getX(), e.getY());
                        }
                    });
                    //use global mouse event capture to disable left click on anything when popup is visible
                    Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
                        @Override
                        public void eventDispatched(AWTEvent event)
                        {
                            MouseEvent me = (MouseEvent)event;
                            if(me.getID() == MouseEvent.MOUSE_PRESSED)
                            {
                                System.out.println("eventDispatched popup.vis="+popup.isVisible());
                                if( me.getButton() == MouseEvent.BUTTON3)
                                {   
                                    System.out.println("BUTTON3");
                                }   
                                else if(me.getButton() == MouseEvent.BUTTON1)
                                {
                                    System.out.println("BUTTON1");
                                    if(popup.isVisible())
                                        me.consume();
                                }
                            }
                        }
                    }, AWTEvent.MOUSE_EVENT_MASK);                      
                    JFrame f = new JFrame();
                    f.setContentPane(contentPane);
                    f.setSize(400, 300);
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    f.setVisible(true);
                }
            });
        }
    }

您可以通过右键单击按钮左侧的稍微测试该示例,然后弹出窗口将显示。然后,如果单击按钮,则不会调用其操作。如果隐藏弹出窗口,则会正常调用该操作。此功能由以下代码行Toolkit.getDefaultToolkit().addAWTEventListener(...)提供。您可以注释掉该行,然后观察该操作将在您目前遇到的任何情况下发生。