JCombobox键盘输入速度

时间:2013-09-30 11:47:32

标签: java performance swing keyboard jcombobox

我有一个JCombobox,上面有很长的项目列表。 为了快速访问,您始终可以键入所需的项目,组合框将引导您进入列表中的项目。 问题是您需要输入的速度非常高,如果您放慢输入项目的速度,Combobox会将您带到列表中的其他项目。

我想知道JCombobox中是否有属性,或者在忘记之前将内存中的键盘输入保持一段时间。

提前致谢。

1 个答案:

答案 0 :(得分:2)

默认的KeySelectionManager只是硬编码1秒钟,以便延迟组合键或开始新搜索,因此您需要创建一个自定义KeySelectionManager,允许您配置搜索延迟。看一下BasicComboBoxUI类中的默认代码。

以下内容或多或少是该代码的副本。它有点复杂,因为它没有直接访问JList。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.*;

public class ComboBoxKeySelection extends JPanel
{
    JComboBox<String> comboBox;

    public ComboBoxKeySelection()
    {
        String[] data =
        {
            " 1", " 2",  " 3", " 4",
            "a", "ab", "abc", "abcd",
            "b1", "b2", "b3", "b4", "be",
            "c", "d", "e", "f"
        };

        comboBox = new JComboBox<String>( data );
        add( comboBox );

        UIManager.put("ComboBox.timeFactor", 3000);
        comboBox.setKeySelectionManager( new MyKeySelectionManager(comboBox) );
    }


    static class MyKeySelectionManager implements JComboBox.KeySelectionManager
    {
        private JComboBox comboBox;
        private JList listBox;
        private boolean useComboBoxModel;

        private int timeFactor;
        private long lastTime;
        private long time;

        private String prefix = "";
        private String typedString = "";

        public MyKeySelectionManager(JComboBox comboBox)
        {
            this.comboBox = comboBox;

            int uiTimeFactor = UIManager.getInt("ComboBox.timeFactor");
            timeFactor = (uiTimeFactor == 0) ? 1000 : uiTimeFactor;

            //  Get the JList used by the UI to hold the comboBox entries

            Object child = comboBox.getAccessibleContext().getAccessibleChild(0);

            if (child instanceof BasicComboPopup)
            {
                BasicComboPopup popup = (BasicComboPopup)child;
                listBox = popup.getList();
                useComboBoxModel = false;
            }
            else
            {
                listBox = new JList();
                useComboBoxModel = true;
            }
        }

        public int selectionForKey(char aKey, ComboBoxModel aModel)
        {
            //  Not using the basic UI so build our own JList to search

            if (useComboBoxModel)
            {
                listBox.setModel( aModel );
            }

            time = System.currentTimeMillis();
            boolean startingFromSelection = true;
            int startIndex = comboBox.getSelectedIndex();

            if (time - lastTime < timeFactor)
            {
                typedString += aKey;

                if((prefix.length() == 1) && (aKey == prefix.charAt(0)))
                {
                    // Subsequent same key presses move the keyboard focus to the next
                    // object that starts with the same letter.
                    startIndex++;
                }
                else
                {
                    prefix = typedString;
                }
            }
            else
            {
                startIndex++;
                typedString = "" + aKey;
                prefix = typedString;
            }

            lastTime = time;

            if (startIndex < 0 || startIndex >= aModel.getSize())
            {
                startingFromSelection = false;
                startIndex = 0;
            }

            int index = listBox.getNextMatch(prefix, startIndex, Position.Bias.Forward);

            if (index < 0 && startingFromSelection)
            {
                // wrap
                index = listBox.getNextMatch(prefix, 0, Position.Bias.Forward);
            }

            return index;
        }
    }


    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("ComboBoxKeySelection");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new ComboBoxKeySelection() );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}