行添加/删除后,JTable返回java.lang.ArrayIndexOutOfBoundsException

时间:2017-09-26 23:45:28

标签: java swing exception jtable

我正在开发一个应该能够在JTable中添加和删除行的自定义组件。

通过使用此功能(例如,添加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);
        }
    }
} 

1 个答案:

答案 0 :(得分:0)

可能与这个旧的Java bug有关:http://bugs.java.com/view_bug.do?bug_id=4730055

尝试在removeSelectedRows:

的末尾添加它
model.fireTableDataChanged();