Не удается получить событие захвата с помощью GRAB_EVENT_MASK? - PullRequest
2 голосов
/ 25 февраля 2010

Я добавил AWTEventListener для обработки события захвата. Так что этот слушатель просто использует sun.awt.SunToolkit.GRAB_EVENT_MASK отметка. Но этот слушатель не может захватить UngrabEvent. Хитрость в том, что когда JComboBox открывает свой menulist, он может захватить это событие. Я использую следующий код для тестирования. Запустите программу, нажмите на пустую область рамки, нажмите на заголовок рамки. Тогда должно быть UngrabEvent. Но слушатель не захватывает это. Запустите программу, нажмите на поле со списком и откройте его список. нажми на заголовок кадра. Тогда должно быть 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 ]

1 голос
/ 26 февраля 2010

Я чувствую, что вы экспериментируете; но, как правило, вы не должны полагаться на недокументированные API Sun / Oracle.

Я хочу всплывающее окно, когда мышь нажимается вне всплывающего окна, но не скрывать при нажатии мыши на всплывающем окне.

Почему бы не вызвать JDialog, когда вы видите isPopupTrigger(), и скрыть его, когда вы видите, что оно деактивируется, когда другое окно активируется? Здесь обсуждается понятие .

0 голосов
/ 15 августа 2018

Хотя рассуждения trashgod понятны, они не отвечают на вопрос: то, что вы на самом деле пытаетесь сделать, не сработает, потому что для захвата даже у вас должно быть окно схватил ((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);
    }
}

Тогда вы получите ваши захватывающие события , но на том уровне, на котором вы работаете, они вам не нужны.

Тогда когда они мне понадобятся?

Предполагая, что вы столкнулись с этой неприятной ошибкой , которая хотя и закрыта, но я все еще могу воспроизвести ее, вам нужно реализовать свой собственный механизм всплывающих окон. Вы все сделали правильно, вы подключили своих слушателей AWT, чтобы закрыть всплывающее окно, когда есть щелчок снаружи, но что-то отсутствует. Вы нажимаете везде, и всплывающее окно исчезает, кроме заголовков окна и за пределами вашего приложения! Стреляй как думаешь! Как это делает JPopupmenu. И после того, как вы потратите некоторое время на чтение jdk-кода и пробуете разные вещи, вы поймете, что именно это недокументированное событие делает свое дело.

Я не знаю внутренностей этого grab() метода, и у меня нет времени исследовать его, поэтому могут быть побочные эффекты, не очень очевидные. Называйте это на свой страх и риск.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...