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

时间:2011-07-14 16:29:25

标签: 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);
    }
}

这是抛出的异常:

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)

3 个答案:

答案 0 :(得分:5)

问题出在这一行:

 listView.updateUI();

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

尝试

 listView.revalidate();

而不是让组件重新布局,或者只是repaint()来重新布局。

答案 1 :(得分:2)

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

编辑:删除不相关的代码

答案 2 :(得分:2)

您应该调用 revalidate()和repaint()方法,而不是 updateUI()。并且可能检查列表中的元素是否真的存在并不是一个坏主意。

        @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();
                }
            }
        }