无法使用GRAB_EVENT_MASK接收抓取事件?

时间:2010-02-25 07:35:36

标签: java swing events

我添加了一个AWTEventListener来处理抓取事件。所以这个监听器只使用sun.awt.SunToolkit.GRAB_EVENT_MASK 标记。 但是这个监听器无法捕获UngrabEvent。棘手的是,当JComboBox弹出其menulist时,它可以捕获此事件。 我使用以下代码进行测试。 启动程序,单击框架的空白区域,单击框架标题。然后应该有一个UngrabEvent。但是听众没有抓住它。 启动程序,单击组合框并使其menulist popuped。点击 框架标题。然后应该有一个UngrabEvent。听众捕捉它。 这很奇怪...... UngrabEvent和JComboBox之间有什么关系吗?

public class ComboboxLearn {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        toolkit.addAWTEventListener(new AWTEventListener() {

            @Override
            public void eventDispatched(AWTEvent event) {
                System.out.println(event);
            }
        }, sun.awt.SunToolkit.GRAB_EVENT_MASK);
        JComboBox box = new JComboBox(new Object[] { "AAA", "BBB", "CCC" });

        box.addPopupMenuListener(new PopupMenuListener() {

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
                System.out.println(e);
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                System.out.println(e);// Set a breakpoint here
            }

            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                System.out.println(e);
            }
        });

        JFrame f = new JFrame();
        f.getContentPane().setLayout(new FlowLayout());
        f.getContentPane().add(box);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(new Dimension(100, 100));

        f.setVisible(true);
    }
}

2 个答案:

答案 0 :(得分:1)

我感觉到你在试验;但通常,您不应该依赖Sun / Oracle的未记录的API。

  

我想要一个可以隐藏的弹出窗口   鼠标在弹出窗口外被按下但是   在弹出窗口上按下鼠标时不会隐藏。

当您看到JDialog时,为什么不调出isPopupTrigger()并在看到它停用时隐藏它,因为另一个窗口会激活?我们讨论了这个概念here

答案 1 :(得分:0)

尽管“垃圾桶”的推理是可以理解的,但它不能回答以下问题:您实际上试图做的事情是行不通的,因为即使要抓火,您也需要有一个抓住的窗口:((SunToolkit)Toolkit.getDefaultToolkit()).grab(someWindow);

您可以按以下方式更改代码

class ComboboxLearn {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        toolkit.addAWTEventListener(new AWTEventListener() {

            @Override
            public void eventDispatched(AWTEvent event) {
                System.out.println(event);
            }
        }, sun.awt.SunToolkit.GRAB_EVENT_MASK);
        JComboBox box = new JComboBox(new Object[] { "AAA", "BBB", "CCC" });

        JFrame f = new JFrame();
        box.addPopupMenuListener(new PopupMenuListener() {

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
                System.out.println(e);
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                System.out.println(e);// Set a breakpoint here
                //UNGRABBING WINDOW
                ((SunToolkit) toolkit).ungrab(f);
            }

            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                System.out.println(e);
                //GRABBING WINDOW
                ((SunToolkit) toolkit).grab(f);
            }
        });

        f.getContentPane().setLayout(new FlowLayout());
        f.getContentPane().add(box);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(new Dimension(100, 100));

        f.setVisible(true);
    }
}

然后,您将获得抓取事件,但是处于您正在处理的级别,不需要它们。

那我什么时候需要它们?

假设您遇到this nasty bug,尽管它已关闭,但我仍然可以重现它,您需要实现自己的弹出机制。您做的一切都很好,只要在外部单击,但缺少某些内容,就可以将AWT侦听器附加到关闭弹出窗口。您随处单击,弹出窗口消失,除了窗口标题和应用程序外!拍你想! JPopupmenu如何做到这一点。在花了一些时间阅读jdk代码并尝试了各种方法之后,您意识到,正是这种未记录的事件才可以解决问题。

我不知道这种grab()方法的内部知识,而且我没有时间去研究,因此可能会有不太明显的副作用。自行承担风险。