I have read through all the threads out there that looked as if they could solve my problem and I've also read all the answers on here, but I'm still at my wit's end. I'm not sure why the exception is thrown, although I have a feeling this might be to do with threading
. If it does, please let me know where to include the new Runnable()
and whether to invokeLater()
or invokeAndWait()
, as I have tried it to no avail.
Please bear with me while I give you the code that leads to the exception + the stacktrace (below).
EDIT: I had included a number of syso
s in the AnnoTable
section just before tableChanged
is called and they don't show up in the console, hence I think the problem must occur even before the application gets to that point, i.e. either when it's called from AAView
or when data and table model are instantiated...
EDIT II: The problem was the overwritten tableChanged
method. That would obviously fire an Exception. I've removed the tableChanged()
call (which wouldn't make a difference) as well. Now I've got another problem: understanding how a change in the underlying data (AnnoData
) can automatically update the table. Although this is perhaps for another query (after an extended Google search), please feel free to post helpful comments in this thread, as I'll continue reading it... THANKS A LOT for all the helpful comments and tips!
EDIT III:* I've solved the problem. I needed to instantiate another object from AnnoData
, pass that to a new instance of AnnoTableModel
, set this instance to my table and THEN fireTableDataChanged()
.
EDIT IV: Okay, so fireTableDataChanged()
(as used in EDIT III) is unnecessary after all. I still would want to use it rather than creating new objects all the time. I guess I should ask a new question... Thanks!
This method in AAView
should create an object extending a JTable
, put it into a JScrollPane
, etc. (the latter does work).
private JPanel createAnnoTablePanel() {
annoTablePanel = new JPanel();
annoTable = new AnnoTable(aameth);
setAnnoTable(annoTable);
JScrollPane scrollPane = new JScrollPane(getAnnoTable());
annoTablePanel.add(scrollPane);
return annoTablePanel;
}
Here is the class AnnoTable
(aameth
is an instance object containing business logic to access a data model, works fine).
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!
}
}
If you need the source code for AnnoTableModel()
(which is a fairly generic extension of AbstractTableModel
) or AnnoData
(which constructs a Vector
containing three Vector<Object>
and a String[]
for column titles), please let me know.
Here's the stacktrace.
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)
I can see the EDT
in there so from what I've learned this might really be a problem of threading. However, I don't know how to find out where I should start a new Thread
(or invoke a new Runnable()
.
On a side note, the Exception only started appearing when I changed AnnoTable
to extend JTable
rather than JPanel
. Originally I had AnnoTable
not only construct the table but also wrap it in a scroll pane and add this to a new JPanel
. But because I wanted to fireTableDataChanged
from a Class that only knew of AAView
(which also features a setAnnoTable()
method) I wanted to do it the correct way, whereas before it worked just fine. Murphy's law?
A rowIndex of -1 (==TableModelEvent.HEADER_ROW) indicates that the model's structure has changed completely. Such an event is fired internally by the JTable on setModel. Read the api doc of TableModelEvent to fully understand which types/values to expect in the listener's tableChanged.
BTW, @AKJ is right - no need to fire any TableModelEvents in your table code. Make the model fire the events as appropriate
This means that you are passing -1
as row or column. This is not permitted - make sure you pass a correct value.
I have a feeling that your problem is here:
TableModelEvent tme = new TableModelEvent(tableModel);
this.tableChanged(tme);
->
int column = e.getColumn();
AbstractTableModel model = (AbstractTableModel)e.getSource();
String columnName = model.getColumnName(column);
Because you haven't specified a row
or column
value, the getColumn()
and getRow()
calls will return -1, which you are then passing to getValueAt()
.
Try looking at the constructor for TableModelEvent. It has options for specifying those row/column values.
TableModelEvent tme = new TableModelEvent(tableModel);
this.tableChanged(tme);
I don't see any need of this call. As pointed by other posters this is the cause of your problem.
If you are implementing the table model correctly, whenever you update the table model the jtable will automatically get notifications and you don't need to write the tableChanged() method as well. So I am lost why you need to call tableChanged() explicitly.
Whenever you want to update the table just update the model. Also at first glance there does not seem to be any threading issue involved.
Your AnnoTable constructor is leaking references to the incompletely constructed "this" object. Also, registering Listeners from the constructor is not safe. enter link description here
Build your objects doing the least amount of work possible in the constructor and then operate on the fully built objects. Add listeners, adjust the models, fireEvents etc...
来源:https://stackoverflow.com/questions/7876090/arrayindexoutofboundsexception-1-on-jtable-creation-tablechanged