开发者

Exception on deleting JList items on keypress

I'm getting a NullPointerException in my JList, but the source of the exception seems to be the Swing event handling code. The JList has a key listener which will delete the selected item when the Delete key is pressed. The exception is only thrown on the second and all subsequent deletions from the list. Any ideas on how to fix it?

Sample code to reproduce the problem and the exception that is produced are included below:

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JList;

public class Sample {

    public static void main(String[] args) {
        final JFrame frame = new JFrame();

        final Vector<String> list = new Vector<String>();
        for (int i = 0; i < 5; ++i) {
            list.add("String " + i);
        }

        final JList listView = new JList(list);

        listView.addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_DELETE) {
                    list.remove(listView.getSelectedIndex());
                    listView.updateUI();
                }
            }

            @Override
            public void keyReleased(KeyEvent e) { }

            @Override
            public void keyTyped(KeyEvent e) { }
        });

        frame.add(listView);

        frame.pack();
        frame.setVisible(true);
    }
}

Here's the exception being thrown:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at javax.swing.plaf.basic.BasicListUI$Handler.isNavigationKey(Unknown Source)
    at javax.swing.plaf.basic.BasicListUI$Handler.keyPressed(Unknown Source)
    at java.awt.AWTEventMulticaster.keyPressed(Unknown Source)
    at java.awt.Component.processKeyEvent(Unknown Source)
    at javax.swing.JComponent.processKeyEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)开发者_运维知识库
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)


The problem is in this line:

 listView.updateUI();

Calling this method causes the current UI to be uninstalled from the JList, yet it is still being used to process events. This results in the NullPointerException you see. This isn't the method you want to call.

Try

 listView.revalidate();

instead to cause the component to re-layout or perhaps just repaint() to get it to repaint.


list.registerKeyboardAction(this,
    KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), JComponent.WHEN_FOCUSED);

EDIT: remove unrelated code


Instead of the updateUI() you should call the revalidate() and repaint() method. And probably a check if the element in the list really exists wouldn't be a bad idea.

        @Override
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_A) {

                if(list.get(listView.getSelectedIndex()) != null) {
                    list.remove(listView.getSelectedIndex());
                    listView.revalidate();
                    listView.repaint();
                }
            }
        }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜