1

I have a JCombobox with a long list of items on it. For quick access you can always type the item you want and the combobox leads you to the item in the list. The problem is that the speed you need to type is quite high and if you slows down typing the item the Combobox leads you to other items of the list.

I wonder if there is a property in JCombobox or a way to hold a little longer the keyboard input in memory before it forgets.

Thanks in advance.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Juan
  • 11
  • 1
  • not this search is based on system properties for double click, never tried to change this property for JList or JComboBox – mKorbel Sep 30 '13 at 11:54
  • but whan array is sorted then wouldn't be caused with this issue, for huge amount of Items (cca 1k) – mKorbel Sep 30 '13 at 11:58
  • > find your solution of this question, possible duplicate [click here](http://stackoverflow.com/questions/11983798/increase-performance-of-jcombobox-with-many-entries) – Sitansu Sep 30 '13 at 11:58

1 Answers1

2

The default KeySelectionManager just hardcodes 1 second for the delay to combine keys or start a new search, so you would need to create a custom KeySelectionManager that allows you to configure the search delay. Take a look at the default code found in the BasicComboBoxUI class.

The following is more or less a copy of that code. It is a little more complicated because it doesn't have direct access to the 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();
            }
        });
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288