【问题标题】:Detect mouse click anywhere on window检测鼠标点击窗口上的任意位置
【发布时间】:2025-11-29 13:00:02
【问题描述】:

我编写了一个 JWindow,它在我的应用程序中有点像一个花哨的菜单,当按下按钮时会弹出。但是,如果用户单击主窗口中的任何位置,我希望它消失。我当然可以将鼠标侦听器添加到主窗口,但这不会将其添加到窗口本身的所有组件中,并且循环遍历所有组件似乎有点暴力解决方案(并且不能如果窗口上的组件发生变化,保证可以工作。)

做这样的事情最好的方法是什么?

【问题讨论】:

标签: java swing mouseevent windowlistener


【解决方案1】:

尝试使用Toolkit.getDefaultToolkit().addAWTEventListener(listener, eventMask)。查找仅过滤鼠标点击的 eventMask。此 AWT 侦听器对整个应用程序是全局的,因此您可以看到所有发生的事件。

【讨论】:

  • +1 请注意:这在安全受限的环境中可能不起作用
  • @kleopatra,你是绝对正确的 (+1)。权限在addAWTEventListener() 中签入。所以,这就是限制。
【解决方案2】:

如果用户单击主窗口中的任何位置,我希望它消失

WindowListener添加到子窗口,然后处理windowDeactiveated()事件并在子窗口上调用setVisible(false)。

工作示例:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class DialogDeactivated
{
    public static void main(String[] args)
    {
        final WindowListener wl = new WindowAdapter()
        {
            public void windowDeactivated(WindowEvent e)
            {
                e.getWindow().setVisible(false);
            }
        };

        JButton button = new JButton("Show Popup");
        button.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                JButton button = (JButton)e.getSource();
                JFrame frame = (JFrame) SwingUtilities.windowForComponent(button);

                JDialog dialog = new JDialog(frame, false);
                dialog.setUndecorated(true);
                dialog.add( new JButton("Dummy Button") );
                dialog.pack();
                dialog.setLocationRelativeTo( frame );
                dialog.setVisible( true );
                dialog.addWindowListener( wl );
            }
        });

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(button, BorderLayout.NORTH);
        frame.setSize(400, 400);
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
     }
}

【讨论】:

  • 我最初尝试了这个,因为它似乎是最简单的方法,但是我 windowDeactiveated() 事件似乎从未注册,这似乎有点奇怪。使用JFrame 效果很好,但是一旦我切换到JWindow。你不知道为什么会这样吗?我现在用另一种方式做了,但我很感兴趣:)
  • @berry120,不确定,但您可以尝试使用未修饰的 JDialog 而不是 JWindow。或者,如果您的问题表明您正在使用精美的菜单,那么为什么不直接使用 t JPopupMenu 并且默认情况下会出现这种行为?
  • 它不完全像一个菜单,有很多方面,例如当您单击一个项目时它会消失,而我并不真正想要 - 更像是菜单和对话框之间的交叉!很难解释,但它在我使用它的上下文中运行良好。确实尝试使用未装饰的 JDialog,但它也不起作用。嗯,我想我会坚持使用 awtevent 方法。不过,感谢您的见解,如果可行,这将是一个更清洁的解决方案!
  • @berry120,它对我来说很好用。你真的在对话框上有一个可聚焦的组件吗?查看 SSCCE 的编辑。
  • 该死 - 我现在觉得很傻。不,我根本没有可聚焦的组件 - 非常感谢这个例子。现在很有意义!