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

BCa*_*rpe 5 java swing menu jpopupmenu

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

  1. 当菜单打开并单击其他位置时,菜单将关闭.
  2. 菜单打开后你点击其他地方,没有其他事情发生.

我已经完成了第一部分.但是当我点击其他地方时,可能会发生其他事件.例如,假设我有按钮A,它执行一些操作,B.目前,如果JPopupMenu打开,并且我单击A,则JPopupMenu关闭并执行B. 我希望JPopupMenu关闭,B不要执行.这可能吗?

谢谢

Ada*_*dam 11

这样做很简单......虽然可以通过一些外观和感觉来覆盖.

UIManager.put("PopupMenu.consumeEventOnClose", Boolean.TRUE);
Run Code Online (Sandbox Code Playgroud)

值得注意的是,这仅消耗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;
}
Run Code Online (Sandbox Code Playgroud)


Bor*_*oro 4

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

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

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);
                }
            });
        }
    }
Run Code Online (Sandbox Code Playgroud)

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