2017-09-26 32 views
0

我正在開發一個應該能夠添加和刪除JTable行的自定義組件。JTable在添加/刪除行後返回java.lang.ArrayIndexOutOfBoundsException

通過具有這種能力(例如添加4行,刪除這些行,添加一個新行,並儘量選擇它)我得到下面的異常彈:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3 >= 1 
at java.util.Vector.elementAt(Vector.java:474) 
at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:664) 
at cnhi_controltower.FDSchedule$ScheduleTable$1.setValueAt(FDSchedule.java:110) 
at javax.swing.JTable.setValueAt(JTable.java:2741) 
at javax.swing.JTable.editingStopped(JTable.java:4723) 
at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:141) 
at javax.swing.AbstractCellEditor.stopCellEditing(AbstractCellEditor.java:85) 
at javax.swing.plaf.basic.BasicTableUI$Handler.mousePressed(BasicTableUI.java:1010) 
at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:280) 
at java.awt.Component.processMouseEvent(Component.java:6532) 
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324) 
at java.awt.Component.processEvent(Component.java:6300) 
at java.awt.Container.processEvent(Container.java:2236) 
at java.awt.Component.dispatchEventImpl(Component.java:4891) 
at java.awt.Container.dispatchEventImpl(Container.java:2294) 
at java.awt.Component.dispatchEvent(Component.java:4713) 
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888) 
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4522) 
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466) 
at java.awt.Container.dispatchEventImpl(Container.java:2280) 
at java.awt.Window.dispatchEventImpl(Window.java:2750) 
at java.awt.Component.dispatchEvent(Component.java:4713) 
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758) 
at java.awt.EventQueue.access$500(EventQueue.java:97) 
at java.awt.EventQueue$3.run(EventQueue.java:709) 
at java.awt.EventQueue$3.run(EventQueue.java:703) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) 
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) 
at java.awt.EventQueue$4.run(EventQueue.java:731) 
at java.awt.EventQueue$4.run(EventQueue.java:729) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) 
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 

是否有人可以幫助我?我到處尋找,但找不到解決方案。 似乎錯誤的參數被傳遞給TableModel的setValueAt(Object,int,int)方法。

這裏是我的代碼:

import javax.swing.*; 
import javax.swing.table.*; 
import java.awt.BorderLayout; 
import java.awt.Component; 
import javax.swing.JSpinner.DateEditor; 
import java.text.*; 
import com.fairdynamics.components.*; 
import java.awt.event.*; 
/** 
* FDSchedule 
*/ 
public class FDSchedule extends JPanel{ 

    private ScheduleTable sc; 
    private CommandPanel p; 
    private final List<Object[]> intervals = new LinkedList(); 
    /** 
    * Default constructor 
    */ 
    public FDSchedule() { 
     super(new BorderLayout()); 
     sc = new ScheduleTable(); 
     JScrollPane sp = new JScrollPane(sc); 
     add(sp,BorderLayout.CENTER); 
     sc.addRow(); 

     p = new CommandPanel(); 
     add(p,BorderLayout.EAST); 
    } 

    private class ScheduleTable extends JTable{ 
     private String[] cols; 
     DefaultTableModel model; 

     public ScheduleTable(){ 
      String[] cols = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun","Start","End"}; 

      model = new DefaultTableModel(cols,0){ 
       @Override 
       public void setValueAt(Object aValue, int row, int column) { 
        super.setValueAt(aValue, row, column); 
        Object[] i = intervals.get(row); 
        if(aValue instanceof Boolean){ 
         i[column] = (boolean)aValue; 
        }else if(aValue instanceof Date){ 
         i[column] = (Date)aValue; 
        } 
       } 
      }; 
      setModel(model); 

      getColumn("Start").setCellRenderer(new TimeRenderer()); 
      getColumn("Start").setCellEditor(new SpinnerEditor()); 
      getColumn("End").setCellRenderer(new TimeRenderer()); 
      getColumn("End").setCellEditor(new SpinnerEditor()); 
     } 

     @Override 
     public Class<?> getColumnClass(int column) { 
      if(column<7){ 
       return Boolean.class; 
      }else{ 
       return Date.class; 
      } 
     } 

     public void addRow(){ 
      Object[] o = {true,true,true,true,true,false,false,new Date(),new Date()}; 
      intervals.add(o); 
      model.addRow(o); 

     } 

     public void removeSelectedRows(){ 
      int[] rows = getSelectedRows(); 
      Arrays.sort(rows); 
      for(int i=rows.length-1; i>=0; i--){ 
       int row = rows[i]; 
       int modelRow = convertRowIndexToModel(row); 
       model.removeRow(modelRow); 
       intervals.remove(row); 
      } 
     } 
    } 

    class TimeRenderer extends DefaultTableCellRenderer{ 

     private final DateFormat f = new SimpleDateFormat("HH:mm"); 

     @Override 
     protected void setValue(Object value) { 
      super.setValue(value); 
      setText((value == null) ? "" : f.format(value)); 
     } 
    } 

    class SpinnerEditor extends AbstractCellEditor implements TableCellEditor { 
     protected JSpinner spinner; 
     private SpinnerDateModel model; 
     public SpinnerEditor() { 
      model = new SpinnerDateModel(); 
      model.setCalendarField(Calendar.HOUR_OF_DAY); 
      spinner = new JSpinner(model); 
      spinner.setEditor(new JSpinner.DateEditor(spinner , "HH:mm")); 
     } 

     public Component getTableCellEditorComponent(JTable table, Object value,boolean isSelected, int row, int column) { 
      spinner.setValue(value); 
      return spinner; 
     } 

     public Object getCellEditorValue() { 
      SpinnerModel sm = spinner.getModel(); 
      return sm.getValue(); 
     } 
    } 

    private class CommandPanel extends JPanel{ 
     public CommandPanel(){ 
      setLayout(new BoxLayout(this,BoxLayout.Y_AXIS)); 
      JButton b = new JButton("Add"); 
      b.addActionListener(new ActionListener(){ 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        sc.addRow(); 
       } 
      }); 
      add(b); 

      b = new JButton("Remove"); 
      b.addActionListener(new ActionListener(){ 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        sc.removeSelectedRows(); 
       } 
      }); 
      add(b); 
     } 
    } 
} 

回答