2011-10-24 32 views
1

我已經通讀了所有線程,看起來好像他們可以解決我的問題,我也閱讀了所有在這裏的答案,但我仍然在我的智慧結束。我不確定爲什麼拋出異常,但我有一種感覺,這可能與threading有關。如果是這樣,請讓我知道在哪裏包括new Runnable()以及是否invokeLater()invokeAndWait(),因爲我已經試過它無濟於事。ArrayIndexOutOfBoundsException:在JTable創建時爲-1/tablechanged

請給我承擔,而我給你的代碼,導致異常+堆棧跟蹤(下)。

編輯:我已經包括了一些syso S IN的AnnoTable節之前tableChanged叫他們不要在控制檯中顯示出來,因此我認爲應用程序獲取到,即使之前必須發生的問題點,即既可以當它是從AAView或者當數據和表格模型實例稱爲...

編輯II:問題是覆蓋tableChanged方法。這顯然會引發異常。我已經刪除了tableChanged()調用(這也沒有什麼區別)。現在我遇到了另一個問題:瞭解基礎數據(AnnoData)中的更改如何自動更新表。雖然這可能是另一個查詢(在擴展的Google搜索之後),但請隨時在本主題中發佈有用的評論,因爲我會繼續閱讀它...感謝所有有用的評論和提示!

編輯三:*我已經解決了這個問題。我需要從AnnoData實例化另一個對象,將其傳遞給AnnoTableModel的新實例,將此實例設置爲我的表,然後fireTableDataChanged()

編輯IV:好吧,所以fireTableDataChanged()(用於編輯III)是不必要的。我仍然希望使用它,而不是始終創建新的對象。我想我應該問一個新問題......謝謝!

這種方法在AAView應該創建一個對象,擴展JTable,把它放到JScrollPane等(後者工作)。

private JPanel createAnnoTablePanel() { 
    annoTablePanel = new JPanel(); 
    annoTable = new AnnoTable(aameth); 
    setAnnoTable(annoTable); 
    JScrollPane scrollPane = new JScrollPane(getAnnoTable()); 
    annoTablePanel.add(scrollPane); 
    return annoTablePanel; 
} 

下面是類AnnoTable(​​是包含業務邏輯來訪問一個數據模型的實例對象,正常工作)。

public class AnnoTable extends JTable implements TableModelListener 
{ 

    public AnnoTable(AAMethods aameth) 
    { 

    int tokenCount = aameth.getTokenCount(); 

    AnnoData annoData = new AnnoData(aameth); // cf. below, AnnoData is a Vector(Vector<Object>,String[]) 

    TableModel tableModel = new AnnoTableModel(annoData.getAnnoData(), 
    // AnnoTableModel extends AbstractTableModel(Vector, String[]) 
    annoData.getColTitles()); 
    setModel(tableModel); 
    getModel().addTableModelListener(this); 
    TableModelEvent tme = new TableModelEvent(tableModel); 
    this.tableChanged(tme); 
    setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
    setCellSelectionEnabled(true); 
    getColumnModel().getSelectionModel().addListSelectionListener(new AnnoTableSelectionListener(this)); 
    setPreferredScrollableViewportSize(this.getPreferredSize()); 

    } 

    public void tableChanged(TableModelEvent e) { 
    int row = e.getFirstRow(); 
    int column = e.getColumn(); 
    AbstractTableModel model = (AbstractTableModel)e.getSource(); 
    String columnName = model.getColumnName(column); 
    Object data = model.getValueAt(row, column); // This is where the exception is thrown! 
    } 
} 

如果您需要AnnoTableModel()的源代碼(這是AbstractTableModel一個非常通用的擴展名)或AnnoData(其構成包含三個Vector<Object>和列標題的String[]一個Vector),請讓我知道。

這是堆棧跟蹤。

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1 
at java.util.Vector.elementAt(Unknown Source) 
at javax.swing.table.DefaultTableModel.getValueAt(Unknown Source) 
at package.AnnoTable.tableChanged(AnnoTable.java:52) 
at javax.swing.JTable.setModel(Unknown Source) 
at javax.swing.JTable.<init>(Unknown Source) 
at javax.swing.JTable.<init>(Unknown Source) 
at package.AnnoTable.<init>(AnnoTable.java:25) 
at package.AAView.createAnnoTablePanel(AAView.java:464) 
at package.AAView.createNorthPanel(AAView.java:455) 
at package.AAView.displayAndAnnotate(AAView.java:444) 
at package.AAView.loadProject(AAView.java:333) 
at package.AAView.actionPerformed(AAView.java:286) 
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.DefaultButtonModel.setPressed(Unknown Source) 
at javax.swing.AbstractButton.doClick(Unknown Source) 
at javax.swing.AbstractButton.doClick(Unknown Source) 
at javax.swing.plaf.basic.BasicMenuItemUI$Actions.actionPerformed(Unknown Source) 
at javax.swing.SwingUtilities.notifyAction(Unknown Source) 
at javax.swing.JComponent.processKeyBinding(Unknown Source) 
at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source) 
at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source) 
at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source) 
at javax.swing.JMenuBar.processKeyBinding(Unknown Source) 
at javax.swing.KeyboardManager.fireBinding(Unknown Source) 
at javax.swing.KeyboardManager.fireKeyboardAction(Unknown Source) 
at javax.swing.JComponent.processKeyBindingsForAllComponents(Unknown Source) 
at javax.swing.JComponent.processKeyBindings(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) 

我可以看到在那裏EDT所以從我學到的東西,這可能真的會穿的問題。但是,我不知道如何找到我應該從哪裏開始新的Thread(或調用new Runnable()

在附註中,僅當我更改AnnoTable以擴展JTable而非JPanel時,異常纔開始出現。我原本AnnoTable不僅構造表,而且在滾動窗格包裝它,這增加了新的JPanel。但是,因爲我想從fireTableDataChanged一類,只知道AAView(其中還設有一個setAnnoTable()方法),我想要做的正確的方式,而在此之前它的工作就好了。墨菲定律?

回答

4

-1(== TableModelEvent.HEADER_ROW)的rowIndex指示模型的結構已完全更改。 setModel上的JTable在內部觸發此類事件。閱讀TableModelEvent的api文檔,以充分了解監聽器的tableChanged中期望的類型/值。

順便說一句,@AKJ是正確的 - 無需在表代碼中觸發任何TableModelEvents。製作模型適當地觸發事件

+0

外觀極好抓+1 – mKorbel

+0

@kleopatra:謝謝。在我的情況當然'則setModel()'會叫我硬編碼'tableChanged()'(參見編輯II),其能接收它沒有收到參數。我已經刪除了該方法。這個表現在可以正確顯示,但是每當'annoData'中的內容發生變化時(通過'annoData'中設置的所有內容''((AbstractTableModel)aaView.getAnnoTable()。getModel()).fireTableDataChanged() ),表格仍然不更新...也許應該在新的查詢中提出這個問題,除非這裏有人有一個快速回答:)。謝謝大家! –

+1

_do不從模型外部的任何代碼調用模型的任何fireXX方法。相反,如果發生任何變化,請實現_model_來執行此操作 – kleopatra

2

這意味着您將通過-1作爲行或列。這是不允許的 - 確保你傳遞正確的值。

2

我有一種感覺,你的問題就在這裏:

TableModelEvent tme = new TableModelEvent(tableModel);  
this.tableChanged(tme); 
-> 
    int column = e.getColumn();  
    AbstractTableModel model = (AbstractTableModel)e.getSource();  
    String columnName = model.getColumnName(column); 

因爲你沒有指定一個rowcolumn值時,getColumn()getRow()調用將返回-1,你再傳遞到getValueAt()

嘗試尋找在構造函數TableModelEvent。它有用於指定那些行/列值的選項。

+0

錯誤 - 上面兩行與異常無關(請參閱stacktrace :-)除此之外,分析是正確的:監聽器代碼必須防止出現「特殊值「(HEADER_ROW,ALL_COLUMNS)行/列索引 – kleopatra

2
TableModelEvent tme = new TableModelEvent(tableModel); 
this.tableChanged(tme); 

我沒有看到任何需要這個調用。正如其他海報所指出的,這是你的問題的原因。

如果您正確地實施了表模型,那麼無論何時更新表模型,jtable都會自動獲取通知,而且您也不需要編寫tableChanged()方法。所以我迷失了爲什麼你需要明確調用tableChanged()。

每當你想更新表只是更新模型。乍一看,似乎沒有涉及任何線程問題。

0

您的AnnoTable構造函數泄漏對未完成構建的「this」對象的引用。另外,從構造函數註冊Listeners是不安全的。 enter link description here

構建您的對象在構造函數中儘可能少地工作,然後對完全構建的對象進行操作。添加監聽器,調整模型,fireEvents等...

相關問題