滚动JComboBox弹出窗口会隐藏它

时间:2011-04-12 18:16:42

标签: java swing jcombobox mousewheel

我的客户抱怨JondeboBox弹出窗口经常在JComboBox弹出窗口上使用滚动而没有垂直滚动条时关闭。 (他似乎意外地使用滚动它,因为他使用的是Apple Magic Mouse鼠标。)

有什么方法可以防止这种情况发生?

我知道它与ComboBoxUI有关,但我想要一些指针从哪里开始。 BasicComboPopup.handler是私有的(不可重用),我没有看到任何与BasicComboPopup中的任何MouseWhellListener相关的代码。

4 个答案:

答案 0 :(得分:6)

source所示,BasicPopupMenuUI包含一个实现MouseGrabber接口的嵌套类AWTEventListenerMouseEvent.MOUSE_WHEELeventDispatched()的收到会取消弹出窗口isInPopup()的功能。我知道没有简单的方法来打败这种行为。

根据经验,此example会从actionPerformed()的{​​{1}}处理程序调用{​​{3}};鼠标滚轮事件被忽略。对于您的用户而言,这可能是一个合理的替代方案,可能与合适的JButton修饰符掩码相结合。

相比之下,此show()会在ActionEvent中调用example来回复show();正如预期的那样,鼠标滚轮事件会取消弹出窗口。

答案 1 :(得分:4)

我测试了组合框的默认行为。当我滚动弹出窗口时它很好,它不会关闭它。但是当我在它外面或甚至在组合框本身上滚动时它会消失。

我不知道你是不是喜欢这样的东西,但是如果我在组合框中检测到移动的话,我已经将鼠标滚轮监听器添加到组合框中,我正在重新设置弹出窗口。 - 此位仅部分解决了滚动组合框时鼠标滚轮不显示组合框的问题。

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提供的解决方案似乎可行,但它看起来很精致:),因此我建议采用另一种方法。

祝你好运,博罗。

答案 2 :(得分:4)

感谢您的建议,我通过黑客攻击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);

谢谢你们!

答案 3 :(得分:1)

这是一个适用于大多数情况的解决方案

var cities = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace(),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: {
        url: "http://gd.geobytes.com/AutoCompleteCity?callback=?&template=<geobytes%20city>,%20<geobytes%20code>&filter=US&q=%QUERY",
        wildcard: "%QUERY",
        dataType: "jsonp",
        transform: function (response) {
            return response;
        }
    },
    limit: 10
});

$("#city").typeahead({
    minLength: 3,
    highlight: true,
    hint: true
}, {
    name: "US-Cities",
    source: cities
});