javakeylistener

Java JList reporting incorrect index when using a KeyListener


I would like to understand why the printed list index for this JLIST Object gets out of sync with the highlighted line when KeyPressedListener fires following up and down key press events, and how I might resolve the issue

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JList;
import java.awt.BorderLayout;

public class ListTest
{

    private JFrame frame;
    private String[] values = new String[] {"Line 0", "Line 1", "Line 2", "Line 3"};

    public static void main(String[] args)
    {
        ListTest window = new ListTest();
        window.frame.setVisible(true);
    }
    public ListTest()
    {

        frame = new JFrame();
        frame.setBounds(100, 100, 136, 153);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JList<String> list = new JList<String>(values);
        frame.getContentPane().add(list, BorderLayout.CENTER);
        list.setSelectedIndex(0);
        list.addKeyListener(new KeyListener()
        {
            @Override
            public void keyReleased(KeyEvent arg0){}
            @Override
            public void keyTyped(KeyEvent arg0){}
            @Override
            public void keyPressed(KeyEvent e)
            {
                int code = e.getKeyCode();

                switch( code ) 
                { 
                case KeyEvent.VK_UP:
                    System.out.println("UP " + list.getSelectedIndex());
                    break;
                case KeyEvent.VK_DOWN:
                    System.out.println("DOWN " + list.getSelectedIndex());
                    break;
                }
            }
        });
    }
}

Solution

  • Because the keyPressed event will return the previous selection.

    Just get the output from the keyReleased event and you'll be fine.

    public void keyReleased(KeyEvent arg0) {
        int code = arg0.getKeyCode();
    
        switch (code) {
            case KeyEvent.VK_UP:
                System.out.println("UP " + list.getSelectedIndex());
                break;
            case KeyEvent.VK_DOWN:
                System.out.println("DOWN " + list.getSelectedIndex());
                break;
        }
    }
    

    Here's a better explanation of keyevents:

    keyPressed(): when the key goes down

    keyReleased(): when the key comes up

    keyTyped(): when the unicode character represented by this key is sent by the keyboard to system input

    The selection of an item in JList happens when the key comes up. When keyReleased is fired the next item in JList will already be selected. But the keyPressed event fires before the selection happens.