Swing鼠标点击事件适用于JMenu和JPopupMenu

3
我希望在Swing中实现Eclipse的鼠标点击菜单和弹出菜单之外的行为。基本上,当您在Eclipse中按下鼠标离开菜单时,菜单会消失,并将鼠标按下事件转发到您用鼠标单击的组件。
令人烦恼的是,Swing没有这样的功能,我找不到解决方法。即使使用Windows LAF,现在我也必须再次单击才能使组件注册鼠标单击事件。
为了方便回复,请在表格上执行此操作。
final JPopupMenu popupMenu = new JPopupMenu();
JMenuItem viewProfile = new JMenuItem("View Profile");
viewProfile.addActionListener(new ActionListener() { 
   public void actionPerformed(ActionEvent e) {
   }
});
popupMenu.add(viewProfile);
table.setComponentPopupMenu(popupMenu);

编辑:这里有一段测试代码。我认为在每个简单组件上添加鼠标监听器以便它们可以在弹出菜单后注册鼠标点击并不方便。在下面的示例中,表格确实实现了它,但按钮没有。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;

public class TestMouse {

   public static void main(String[] args) {
      new TestMouse();
   }

   private JLabel  counter;

   private int     count;

   private JPanel  northPanel;

   private JButton clickMe;

   public TestMouse() {
      EventQueue.invokeLater(new Runnable() {

         @Override
         public void run() {
            try {
               UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            }

            DefaultTableModel model = new DefaultTableModel(new Object[] { "A", "B", "B", "B", "B", "B", "B" }, 10);
            JTable table = new JTable(model);

            northPanel = new JPanel();

            clickMe = new JButton("Button");
            clickMe.addActionListener(new ActionListener() {

               @Override
               public void actionPerformed(ActionEvent e) {
                  System.out.println("clicked");
                  count++;
               }
            });
            counter = new JLabel("0");

            northPanel.add(counter);
            northPanel.add(clickMe);

            final JPopupMenu popupMenu = new JPopupMenu();
            JMenuItem viewProfile = new JMenuItem("View Profile");
            viewProfile.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
               }
            });
            popupMenu.add(viewProfile);
            table.setComponentPopupMenu(popupMenu);
            table.addMouseListener(new MouseAdapter() {

               @Override
               public void mouseClicked(MouseEvent e) {
                  System.out.println("clicked");
                  count++;
                  counter.setText(String.valueOf(count));
               }

            });

            JFrame frame = new JFrame("Testing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new BorderLayout());
            frame.add(northPanel, BorderLayout.NORTH);
            frame.add(new JScrollPane(table));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
         }
      });
   }

}
2个回答

4

我似乎无法复制这个问题。

当我右键点击表格时,弹出菜单会出现,当我再次点击表格(以关闭弹出窗口)时,将触发mouseClicked事件。

ClicktyClack

请注意北侧的计数器...

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;

public class TestMouse {

    public static void main(String[] args) {
        new TestMouse();
    }

    private JLabel counter;
    private int count;

    public TestMouse() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                DefaultTableModel model = new DefaultTableModel(
                        new Object[]{"A", "B", "B", "B", "B", "B", "B"},
                        10
                );
                JTable table = new JTable(model);
                counter = new JLabel("0");

                final JPopupMenu popupMenu = new JPopupMenu();
                JMenuItem viewProfile = new JMenuItem("View Profile");
                viewProfile.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                    }
                });
                popupMenu.add(viewProfile);
                table.setComponentPopupMenu(popupMenu);
                table.addMouseListener(new MouseAdapter() {

                    @Override
                    public void mouseClicked(MouseEvent e) {
                        System.out.println("clicked");
                        count++;
                        counter.setText(String.valueOf(count));
                    }

                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(counter, BorderLayout.NORTH);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

一个实际的可运行的示例,可以展示您的问题,将会减少猜测并获得更好的回答。


很好的回答开端。但我想要的是系统或弹出系统级别的东西。我认为在每个组件上添加鼠标监听器不是一个好的设计思路。对于JButton常规鼠标事件,您不需要鼠标监听器。为什么我们需要一个来隐藏弹出窗口的鼠标事件呢? - Mordan
弹出窗口会在失去焦点时自动关闭。按钮有它们自己的鼠标监听器,触发操作监听器。您想实现什么目标? - MadProgrammer

3

当我关闭JMenuBar弹出窗口时,我遇到了完全相同的问题,这个方法对我有用:

UIManager.put("PopupMenu.consumeEventOnClose", false);

哦,我的天啊,这是一块信息黄金!这种行为在过去的几年里已经让我疯狂了不止一次。 - Reto Höhener

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接