Java 如何在关闭JPopupMenu时通过单击其外部来防止触发其他事件?
我想用JPopupMenu复制右键单击上下文菜单的一些属性:Java 如何在关闭JPopupMenu时通过单击其外部来防止触发其他事件?,java,swing,menu,jpopupmenu,Java,Swing,Menu,Jpopupmenu,我想用JPopupMenu复制右键单击上下文菜单的一些属性: 当菜单打开并单击其他位置时,菜单关闭 当菜单打开并单击其他位置时,不会发生任何其他情况 我把第一部分写得很好。但当我点击其他地方时,其他事件可能会发生。例如,假设我有一个按钮A,它执行一些动作B。当前,如果JPOPUP菜单打开,我单击A,JPOPUP菜单关闭,B被执行。我希望JPOPUPMENUS关闭,并且不执行B。这可能吗 谢谢考虑到您在问题和评论中所说的内容,我将用以下方法之一解决您的问题 从技术上讲,您有两种选择: 1.每当用户
谢谢考虑到您在问题和评论中所说的内容,我将用以下方法之一解决您的问题 从技术上讲,您有两种选择: 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(…)
提供。您可以注释掉该行,并观察到该操作将在您当前体验的任何情况下发生。这是有效的,而且简单得多。。。虽然可以被一些外观和感觉所覆盖
UIManager.put("PopupMenu.consumeEventOnClose", Boolean.TRUE);
还值得注意的是,这只会消耗鼠标按下事件,而不会消耗后续的鼠标点击事件。您可以通过在mousePressed()中设置标志并在mouseReleased()中测试来模拟单击的鼠标。如果最初按下的鼠标已被使用,则不会在mouseReleased()中设置该标志
我不明白为什么您不希望在用户单击按钮事件时触发该事件,但每当触发JPopupMenu事件时,请禁用按钮单击事件,然后在菜单关闭时重新启用该事件。@BCarpe,这是“检查然后执行”的简单情况吗?在打开
jpopmpmenu
时设置一个标志,然后在actionPerformed
方法中进行检查,该方法仅在未设置标志的情况下执行例行程序。这只是惯例。你自己试试看。在浏览器上单击鼠标右键,然后单击任意位置。它总是先关闭,然后再让您单击任何其他内容。至于禁用/重新启用,我有很多组件,并且可能会添加更多,因此跟踪该机制将增加比我实际能够处理的更复杂的一点。@mre,我真的不想在每个组件中加入处理这种情况的方法。关闭时是否有JPOppMenu发出的信号--编辑--PopupMenuListener执行此操作。@BCarpe如果我在浏览器中单击鼠标右键,然后单击与我所在选项卡不同的选项卡,它将选择新选项卡。(Chrome)谢谢!是的,globals侦听器正是我想要的。禁用此行为对我很有用:)当弹出菜单已经打开时,它会导致后续右键单击出现问题,显示新菜单但不选择行。我的问题正好相反。当我检查该值时,该值为true,因此我将其设置为false(并再次检查它是否保持false),但我的事件仍然被消耗。
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;
}