在keypress上删除JList项目的例外情况

Dav*_* S. 4 java swing jlist

我在JList中遇到NullPointerException,但异常的来源似乎是Swing事件处理代码.JList有一个键监听器,当按下Delete键时,它将删除所选项.仅在列表中的第二个和所有后续删除上抛出异常.关于如何修复它的任何想法?

重现问题的示例代码和生成的异常包括在下面:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是抛出的异常:

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)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

问题出在这一行:

 listView.updateUI();
Run Code Online (Sandbox Code Playgroud)

调用此方法会导致当前UI从中卸载JList,但它仍然用于处理事件.这导致NullPointerException你看到了.这不是您要调用的方法.

尝试

 listView.revalidate();
Run Code Online (Sandbox Code Playgroud)

而是让组件重新布局,或者只是repaint()让它重新绘制.