2013-07-12 58 views
3

我一直在浏览这个网站,并尝试了一些不同的东西,但即时通讯难倒。将不胜感激的一些帮助。 条件工作,检查是否选中复选框(真),但我做model.removeRow(row)它会给我这个错误。JTable删除行给ArrayOutofBounds异常-1

public class ExpenditurePanel extends JPanel implements TableModelListener{ 

private static final long serialVersionUID = 1L; 
private static TableModel1 model; 
private JTable table; 

public ExpenditurePanel() { 
    model = new TableModel1(); 
    table = new JTable(model); 
    table.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null)); 
    table.setRowSelectionAllowed(false); 
    table.setFillsViewportHeight(true); 
    table.setCellSelectionEnabled(true); 
    table.setColumnSelectionAllowed(false); 

    model.addColumn("Name"); 
    model.addColumn("Week"); 
    model.addColumn("Fortnight"); 
    model.addColumn("Month"); 
    model.addColumn("Year"); 
    model.addColumn("Remove"); 

    Object[] default1 = {"Accomodation","","","","",false}; 
    Object[] default2 = {"Food","","","","",false}; 

    model.addRow(default1); 
    model.addRow(default2); 

    model.addTableModelListener(this); 

    this.add(new JScrollPane(table)); 
    table.setRowSorter(null); 

} 

public static TableModel1 getModel(){ 
    return model; 
} 

@Override 
public void tableChanged(TableModelEvent e) { 
    int row = e.getFirstRow(); 
    int column = e.getColumn(); 
    model = (TableModel1) e.getSource(); 
    String columnName = model.getColumnName(column); 
    Object data = model.getValueAt(row, column); 

    if(model.getValueAt(row,column) == Boolean.TRUE){ 
     System.out.println("Condition working"); 

     //this part keeps giving me error. 
     model.removeRow(row); 
    } 
} 
} 

这是它抛出:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1 
at java.util.Vector.elementData(Unknown Source) 
at java.util.Vector.elementAt(Unknown Source) 
at javax.swing.table.DefaultTableModel.getValueAt(Unknown Source) 
at studentBudget.ExpenditurePanel.tableChanged(ExpenditurePanel.java:53) 
at javax.swing.table.AbstractTableModel.fireTableChanged(Unknown Source) 
at javax.swing.table.AbstractTableModel.fireTableRowsDeleted(Unknown Source) 
at javax.swing.table.DefaultTableModel.removeRow(Unknown Source) 
at studentBudget.ExpenditurePanel.tableChanged(ExpenditurePanel.java:59) 
at javax.swing.table.AbstractTableModel.fireTableChanged(Unknown Source) 
at javax.swing.table.AbstractTableModel.fireTableCellUpdated(Unknown Source) 
at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source) 
at javax.swing.JTable.setValueAt(Unknown Source) 
at javax.swing.JTable.editingStopped(Unknown Source) 
at javax.swing.AbstractCellEditor.fireEditingStopped(Unknown Source) 
at javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(Unknown Source) 
at javax.swing.DefaultCellEditor.stopCellEditing(Unknown Source) 
at javax.swing.DefaultCellEditor$EditorDelegate.actionPerformed(Unknown Source) 
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) 
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) 
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) 
at javax.swing.JToggleButton$ToggleButtonModel.setPressed(Unknown Source) 
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) 
at java.awt.Component.processMouseEvent(Unknown Source) 
at javax.swing.JComponent.processMouseEvent(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 javax.swing.plaf.basic.BasicTableUI$Handler.repostEvent(Unknown Source) 
at javax.swing.plaf.basic.BasicTableUI$Handler.mouseReleased(Unknown Source) 
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source) 
at java.awt.Component.processMouseEvent(Unknown Source) 
at javax.swing.JComponent.processMouseEvent(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.LightweightDispatcher.retargetMouseEvent(Unknown Source) 
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) 
at java.awt.LightweightDispatcher.dispatchEvent(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$3.run(Unknown Source) 
at java.awt.EventQueue$3.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.awt.EventQueue$4.run(Unknown Source) 
at java.awt.EventQueue$4.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$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

查看**编辑2 **回答提供了一个可能的解决方案。 –

回答

3

您正在改变TableModel的一个TableModelListener的内部,这似乎只是一个有点冒险对我是不想要的递归的风险。我会重新考虑你的代码,以便尽可能不要这样做。如果您仍然卡住,那么您应该创建并发布sscce


编辑1

如果我做一个sscce出你的代码,并添加println语句:

import javax.swing.*; 
import javax.swing.border.BevelBorder; 
import javax.swing.event.*; 
import javax.swing.table.*; 

public class ExpenditurePanel extends JPanel implements TableModelListener { 

    private static final long serialVersionUID = 1L; 
    private static TableModel1 model; 
    private JTable table; 

    public ExpenditurePanel() { 
     model = new TableModel1(); 
     table = new JTable(model); 
     table.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, 
      null)); 
     table.setRowSelectionAllowed(false); 
     table.setFillsViewportHeight(true); 
     table.setCellSelectionEnabled(true); 
     table.setColumnSelectionAllowed(false); 

     model.addColumn("Name"); 
     model.addColumn("Week"); 
     model.addColumn("Fortnight"); 
     model.addColumn("Month"); 
     model.addColumn("Year"); 
     model.addColumn("Remove"); 

     Object[] default1 = { "Accomodation", "", "", "", "", false }; 
     Object[] default2 = { "Food", "", "", "", "", false }; 

     model.addRow(default1); 
     model.addRow(default2); 

     model.addTableModelListener(this); 

     this.add(new JScrollPane(table)); 
     table.setRowSorter(null); 

    } 

    public static TableModel1 getModel() { 
     return model; 
    } 

    @Override 
    public void tableChanged(TableModelEvent e) { 
     int row = e.getFirstRow(); 
     int column = e.getColumn(); 

     // **** printf added below 
     System.out.printf("[row: %d, column: %d]%n", row, column); 

     model = (TableModel1) e.getSource(); 

     String columnName = model.getColumnName(column); 

     // **** println added below 
     System.out.println("columnName: " + columnName); 

     Object data = model.getValueAt(row, column); 

     if (model.getValueAt(row, column) == Boolean.TRUE) { 
     System.out.println("Condition working"); 

     // *** AIOOBE called here 
     model.removeRow(row); 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      ExpenditurePanel panel = new ExpenditurePanel(); 
      JFrame frame = new JFrame("foo"); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.getContentPane().add(panel); 
      frame.setLocationRelativeTo(null); 
      frame.pack(); 
      frame.setVisible(true); 
     } 
     }); 
    } 
} 

// **** no idea how close this is to your code ***** 
class TableModel1 extends DefaultTableModel { 
    @Override 
    public Class<?> getColumnClass(int columnIndex) { 
     if (getRowCount() == 0) { 
     return super.getColumnClass(columnIndex); 
     } 
     Object value = getValueAt(0, columnIndex); 
     if (value == null) { 
     return super.getColumnClass(columnIndex); 
     } 

     return value.getClass(); 
    } 
} 

我得到这样的输出:

[row: 0, column: 5] 
columnName: Remove 
Condition working 
[row: 0, column: -1] 
columnName: 
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1 
    at java.util.Vector.elementAt(Unknown Source) 
    ...... etc ...... 

所以你看模型听众的tableChanged(...)方法被称为两次由于更改侦听器内的侦听对象发生递归,第二次调用时,它有一列-1,这会导致您的AIOOBE被抛出。


编辑2
的潜在解决方案是使模型更改之前除去听者,然后重新添加使变更后的监听器:

public void tableChanged(TableModelEvent e) { 
    int row = e.getFirstRow(); 
    int column = e.getColumn(); 
    System.out.printf("[row: %d, column: %d]%n", row, column); 
    model = (TableModel1) e.getSource(); 
    String columnName = model.getColumnName(column); 
    System.out.println("columnName: " + columnName); 
    Object data = model.getValueAt(row, column); 

    if (model.getValueAt(row, column) == Boolean.TRUE) { 
    System.out.println("Condition working"); 

    model.removeTableModelListener(this); 
    model.removeRow(row); 
    model.addTableModelListener(this); 
    } 
} 
+0

感谢您的帮助。它现在从您的潜在解决方案开始工作虐待你的话,看看我能否理解为什么这样做。真的很感激它! – Sam

+0

@Sam:不客气。问题是你的代码改变了触发TableModelListener的表格模型,这会改变触发....等等的表格模型,看看我要去哪里? –

+0

是的,这很清楚。干杯! – Sam

1

为了详细描述一在@ Hover的正确跟踪并假设一个有效的用例如“我们有一个作业列表,如果完成一个从列表中删除该作业”:

您的基本问题监听器是它不检查通知哪种类型的更改:您只对特定列的更新感兴趣,而不是其他任何其他(fi。就像删除行一样),导致第二个通知出现错误:已删除的typEvent类型列有-1

解决方法是添加检查,如果触发器不是更新具体列:

@Override 
public void tableChanged(TableModelEvent e) { 
    if (!TableUtilities.isUpdate(e)) return; 
    ... 
} 

分析一个TableModelEvent是有点不方便(不完全直观的条件,需要TableModelEvent的javadoc的通读) - 这是我懒得去保持它在内存中,所以有一个实用工具类SwingX,为方便起见复制相关部分:

/** 
* Returns a boolean indication whether the event represents a 
* dataChanged type. 
* 
* @param e the event to examine. 
* @return true if the event is of type dataChanged, false else. 
*/ 
public static boolean isDataChanged(TableModelEvent e) { 
    if (e == null) 
     return false; 
    return e.getType() == TableModelEvent.UPDATE && e.getFirstRow() == 0 
      && e.getLastRow() == Integer.MAX_VALUE; 
} 

/** 
* Returns a boolean indication whether the event represents a 
* update type. 
* 
* @param e the event to examine. 
* @return true if the event is a true update, false 
*   otherwise. 
*/ 
public static boolean isUpdate(TableModelEvent e) { 
    if (isStructureChanged(e)) 
     return false; 
    return e.getType() == TableModelEvent.UPDATE 
      && e.getLastRow() < Integer.MAX_VALUE; 
} 

/** 
* Returns a boolean indication whether the event represents a 
* insert type. 
* 
* @param e the event to examine 
* @return true if the event is of type insert, false otherwise. 
*/ 
public static boolean isInsert(TableModelEvent e) { 
    if (e == null) return false; 
    return TableModelEvent.INSERT == e.getType(); 
} 


/** 
* Returns a boolean indication whether the event represents a 
* structureChanged type. 
* 
* @param e the event to examine. 
* @return true if the event is of type structureChanged or null, false 
*   else. 
*/ 
public static boolean isStructureChanged(TableModelEvent e) { 
    return e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW; 
} 
+0

1+教育我一如既往,谢谢!对不起,跳到主题,但请在评论中权衡[this](http://stackoverflow.com/a/17626773/522444)讨论。 –

0

只是要这样:

clsController.getTable().setSortable(false); 
model.removeRow(selectedModelRow); 
clsController.getTable().setSortable(true); 

和它的作品!

0

您可以查看它的事件类型。这样做,您可以跳过tableChanged方法的内容进行添加和删除。

public void tableChanged(TableModelEvent e) { 
    int type = e.getType(); 

    if (type != TableModelEvent.DELETE && type != TableModelEvent.INSERT) { 

    // operation only for update 

    } 
}