Search code examples
javaswingjlist

Shortcut in java swing JList


I have a java swing JList and want to be able to use DOUBLE keys to move to a certain line in the list. Look at my list below. If I press key 2 focus in the list jumps to line 2002. But I want to be able to press key 22 (two 2:s) and focus jumps to 2201.

My list:

1001
1002
1003
1101
1102
1103
2002
2003
2004
2201
2202

Anyone knows if this is even possible for a JList?


Solution

  • This is controlled by the LAF.

    The default logic states that when you enter the same key the list will just cycle to the next item in the list.

    So you can't go directly to the "22..." numbers as it will go through each item starting with a "2...".

    However if you have a number like "2301" and "2311" you would be able to go directly to those numbers.

    Here is the logic found in the BasicListUI class:

    public void keyTyped(KeyEvent e) {
        JList src = (JList)e.getSource();
        ListModel model = src.getModel();
    
        if (model.getSize() == 0 || e.isAltDown() ||
                BasicGraphicsUtils.isMenuShortcutKeyDown(e) ||
                isNavigationKey(e)) {
            // Nothing to select
            return;
        }
        boolean startingFromSelection = true;
    
        char c = e.getKeyChar();
    
        long time = e.getWhen();
        int startIndex = adjustIndex(src.getLeadSelectionIndex(), list);
        if (time - lastTime < timeFactor) {
            typedString += c;
            if((prefix.length() == 1) && (c == 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 = "" + c;
            prefix = typedString;
        }
        lastTime = time;
    
        if (startIndex < 0 || startIndex >= model.getSize()) {
            startingFromSelection = false;
            startIndex = 0;
        }
        int index = src.getNextMatch(prefix, startIndex,
                                     Position.Bias.Forward);
        if (index >= 0) {
            src.setSelectedIndex(index);
            src.ensureIndexIsVisible(index);
        } else if (startingFromSelection) { // wrap
            index = src.getNextMatch(prefix, 0,
                                     Position.Bias.Forward);
            if (index >= 0) {
                src.setSelectedIndex(index);
                src.ensureIndexIsVisible(index);
            }
        }
    }
    

    Note the comment where the "prefix" variable is set.

    So if you want to change the behaviour you would need to create a custom UI and override the method. Don't know if the method uses privates variables or methods.

    Or the other choice would be to remove the default KeyListener from the JList. Then you could implement your own KeyListener and invoke the getNextMatch(...) directly with your custom determined prefix.