有右键关联菜单的一些性质,我想用JPopupMenu的复制:如何防止通过点击外部关闭JPopupMenu时触发其他事件?
- 当菜单打开并单击其他地方,菜单关闭。
- 当菜单打开并在其他地方点击时,没有其他事情发生。
我已经把第一部分弄好了。但是当我点击其他地方时,可能会发生其他事件。例如,假设我有按钮A,它执行一些操作B.目前,如果JPopupMenu已打开,并且我单击A,则JPopupMenu关闭并执行B.我宁愿JPopupMenu关闭和B不执行。这可能吗?
感谢
有右键关联菜单的一些性质,我想用JPopupMenu的复制:如何防止通过点击外部关闭JPopupMenu时触发其他事件?
我已经把第一部分弄好了。但是当我点击其他地方时,可能会发生其他事件。例如,假设我有按钮A,它执行一些操作B.目前,如果JPopupMenu已打开,并且我单击A,则JPopupMenu关闭并执行B.我宁愿JPopupMenu关闭和B不执行。这可能吗?
感谢
考虑到什么是你的问题和评论说,我会在下面的方法之一来解决你的问题。
从技术上讲,你这里有两种选择:
1.Hide每当用户移动鼠标在弹出的外弹出。这样你就没有用户点击的问题,因为弹出窗口本身就会消失。
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(...)
提供。您可以对该行进行注释,并观察该行为在任何情况下都会在您目前遇到的情况下发生。
谢谢!是的,全球性的听众正是我所期待的。 – BCarpe 2011-06-09 14:51:48
这有效,并且简单得多...虽然可以被一些外观和感觉覆盖。
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,我不知道这个事实。这太神奇了:-) – 2012-03-10 11:38:46
这对我来说是非常有用的,可以禁用这种行为:)当随后的右键单击时,弹出式菜单已经打开,显示新菜单但未选择该行,导致出现问题。 – 2014-05-12 01:28:44
我有完全相反的问题。当我检查它时,这个值是真的,所以我将它设置为false(并且仔细检查它保持为false),但是我的事件仍然被消耗。 – 2015-07-14 10:25:10
我不明白为什么你不想让按钮触发事件,当用户在其上点击,但每当JPopupMenu事件被触发,禁用按钮单击事件,然后在菜单关闭时重新启用事件。 – 2011-06-03 17:22:20
@BCarpe,这是“check-then-act”的简单例子吗?在打开'JPopupMenu'时设置一个标志,然后在你的'actionPerformed'方法中检查只有在没有设置标志时才会执行它们的例程。 – mre 2011-06-03 17:32:02
这只是约定。自己尝试一下。右键单击您的浏览器,然后单击任何地方。它总是先关闭,然后让你点击其他任何东西。至于禁用/重新启用,我有很多组件,可能会增加更多,所以跟踪该机制会增加一点复杂性,比我真正处理。 – BCarpe 2011-06-03 17:33:34