2013-07-12 35 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 

    } 
}