2011-07-14 25 views
4

我在我的JList中收到NullPointerException異常,但異常的來源似乎是Swing事件處理代碼。 JList有一個按鍵監聽器,當按下Delete鍵時,它將刪除所選項目。該異常僅在列表中的第二次和隨後的所有刪除操作上引發。任何想法如何解決它?刪除按鍵上的JList項目的異常

示例代碼重現該問題和所產生以下都包括在異常:

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) 
+0

另外:代替使用'KeyListener',嘗試['KeyAdapter'](http://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyAdapter。 HTML)。 – wchargin

回答

5

的問題是在這條線:

listView.updateUI(); 

調用此方法會導致當前UI從中被卸載,但它仍被用於處理事件。這會導致您看到NullPointerException。這不是你想要調用的方法。

嘗試

listView.revalidate(); 

而不是導致組件重新佈局或者只是repaint()讓它重新繪製。

+0

調用revalidate()似乎沒有效果,但重繪()是訣竅。感謝您解釋異常的來源。 –

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

編輯:去掉無關的代碼

2

取而代之的是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(); 
       } 
      } 
     }