Прокрутка во всплывающем окне JComboBox скрыть это - PullRequest
5 голосов
/ 12 апреля 2011

Мой клиент жалуется, что всплывающие окна JComboBox часто закрываются, когда используется прокрутка поверх всплывающего окна JComboBox без вертикальной полосы прокрутки.(Кажется, он случайно использовал прокрутку поверх нее, потому что использует мышь Apple Magic Mouse.)

Есть ли способ предотвратить это?

Я знаю, что это связано с ComboBoxUI, ноЯ хотел бы несколько указателей, с чего начать.BasicComboPopup.handler является закрытым (не подлежит повторному использованию), и я не вижу никакого кода относительно любого MouseWhellListener в BasicComboPopup.

Ответы [ 4 ]

6 голосов
/ 13 апреля 2011

Как видно из источника , BasicPopupMenuUI содержит вложенный класс MouseGrabber, который реализует интерфейс AWTEventListener. Получение MouseEvent.MOUSE_WHEEL в eventDispatched() отменяет всплывающее окно как функцию isInPopup(). Я не знаю простого способа победить поведение.

Опытным путем, этот пример вызывает show() из обработчика actionPerformed() объекта JButton; События колеса мыши игнорируются. Это может быть разумной альтернативой для вашего пользователя, возможно, в сочетании с подходящей маской-модификатором ActionEvent.

Напротив, этот пример вызывает show() в ответ на isPopupTrigger() в MouseAdapter; как и ожидалось, события колеса мыши отменяют всплывающее окно.

4 голосов
/ 13 апреля 2011

Благодаря вашему предложению у меня появилась идея найти решение, взломав AWTEventListeners.

    Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener()
    {
        public void eventDispatched(AWTEvent event)
        {
            if (event instanceof MouseWheelEvent)
            {
                Object source = event.getSource();
                if ((source instanceof JScrollPane) &&
                    (((JScrollPane) source).getParent().getClass().
                       getName().equals("com.apple.laf.AquaComboBoxPopup")))
                {
                    JViewport viewport = ((JScrollPane) source).getViewport();
                    if (viewport.getViewSize().height <= viewport.getHeight())
                        // prevent consuming if there is a vertical scrollbar
                        ((MouseWheelEvent) event).consume();
                }
            }
        }
    }, AWTEvent.MOUSE_WHEEL_EVENT_MASK);

Спасибо, ребята!

4 голосов
/ 13 апреля 2011

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

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

import java.awt.HeadlessException;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ComboBoxMouseWheel
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createGUI();
            }
        });
    }

    private static void createGUI() throws HeadlessException
    {
        String[] items = new String[]
        {
            "oasoas", "saas", "saasas"
        };
        final JComboBox jcb = new JComboBox(items);
        jcb.addMouseWheelListener(new MouseWheelListener()
        {
            @Override
            public void mouseWheelMoved(MouseWheelEvent e)
            {
                System.out.println("ohjasajs");
                e.consume();
                jcb.showPopup();
            }
        });
        JPanel p = new JPanel();
        p.add(jcb);
        JPanel contentPane = new JPanel();
        contentPane.add(p);
        JFrame f = new JFrame();
        f.setContentPane(contentPane);
        f.setSize(300, 300);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}

Надеюсь, что это даже полезноЕсли вам удастся решить другой путь, пожалуйста, поделитесь им с нами.Решение, предоставленное @trashgod, кажется выполнимым, но выглядит очень тщательно продуманным :), поэтому я предлагаю свой подход к альтернативе.

Удачи, Боро.

1 голос
/ 28 апреля 2015

Вот решение, которое будет работать в большинстве случаев

Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
            public void eventDispatched(AWTEvent event) {
                if (event instanceof MouseWheelEvent) {
                    Object source = event.getSource();

                    if (source instanceof JScrollPane) {
                        JScrollPane scroll = (JScrollPane) source;
                        if (scroll.getName().equals("ComboBox.scrollPane")) {
                            MouseWheelEvent sourceEvent = ((MouseWheelEvent) event);

                            for (MouseWheelListener listener : scroll.getListeners(MouseWheelListener.class)) {
                                listener.mouseWheelMoved(sourceEvent);
                            }

                            sourceEvent.consume();
                        }
                    }


                }
            }
        }, AWTEvent.MOUSE_WHEEL_EVENT_MASK);
...