|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
IndexOutOfBoundsException on custom table implementationHello everyone,
I've searched these forums for all IndexOutOfBoundsExceptions but none have unfortunately solved my issue. Basically, I'm using SWT and trying to implement GlazedLists onto the Nebula grid widget (which does not use a table model implementation nor a viewer so I have to manually add/delete items). I used the KTable implementation without problem, but unfortunately I cannot use KTable anymore due to that it's not being worked on and there's quite a few issues with it. Everything works fine for sorting and such, but when I do filtering I run into OutOfBounds issues. I even get OOB issues when my DELETE/UPDATE code does absolutely nothing to the table itself. If I replace everything in the table with what's in the event list then it all works, but doing that means I lose selection and these tables are loaded with data, so it's not really an option. It seems I must be breaking something when I iterate over the changed list, but I can't for the life of me figure out what. Here's my implementation in short snippets: Main constructor (the important bits)
public class NGridTable(List<MyTableObject> input)
EventList<MyTableObject> eventList = GlazedLists.eventList(input);
SortedList<MyTableObject> sortedList = new SortedList<MyTableObject>(eventList, new OurObjectComparator(this));
FilterList<MyTableObject> filterList = new FilterList<MyTableObject>(sortedList, filterMatcher);
// pass the filter list as source list to our "fake model"
NGridTableModel model = new NGridTableModel(this, table, filterList, fixTableFormat)
}
"Fake model":
public class NGridTableModel implements ListEventListener<MyTableObject> {
public NGridTableModel(NGridTable parent, Grid table, EventList<MyTableObject> source,
TableFormat<MyTableObject> tableFormat) {
source.addListEventListener(this);
}
public synchronized void listChanged(ListEvent<MyTableObject> listChanges) {
while (listChanges.next()) {
List<MyTableObject> list = listChanges.getSourceList();
int sourceIndex = listChanges.getIndex();
int changeType = listChanges.getType();
MyTableObject obj = list.get(sourceIndex);
switch (changeType) {
case ListEvent.DELETE:
removeItem(sourceIndex);
break;
case ListEvent.INSERT:
addItem(obj, sourceIndex);
break;
case ListEvent.UPDATE:
// we redraw the table at the end, no need
break;
}
}
table.redraw();
}
}
method applying (and re-applying) the filter:
public void filterWasModified(Matcher<MyTableObject> newMatcher) {
try {
filterList.getReadWriteLock().writeLock().lock();
filterList.setMatcher(newMatcher);
} catch (Exception err) {
FixLogManager.error(err);
} finally {
filterList.getReadWriteLock().writeLock().unlock();
}
}
Typical exception being thrown:
And on a similar note. Just trying to call Am I doing something fundamentally wrong? I've tried pretty much everything, including (SWT) proxied lists, transformed lists, threadsafe lists, order of creating the lists, and so on, but they all end up with the same problem. Would really appreciate any input, I've tried for 6 hours straight and my head feels ready to explode. The fact that clear() fails with a similar exceptions seems I should be able to pinpoint the problem, but I just can't seem to find anything that works, and it keeps coming back to the iterator...
Best regards, |
|
|
Re: IndexOutOfBoundsException on custom table implementationDear Wingnut,
Some of the code in your ListEventListener isn't correct. Specifically, the problem is this: MyTableObject obj = list.get(sourceIndex); This line of code is executed regardless of the change type. But, if the change type is a DELETE, then the source EventList NO LONGER CONTAINS THAT DATA. i.e., the index may now be out of bounds. Change the looping code to resemble this: public void listChanged(ListEvent<MyTableObject> listChanges) {and it should be faster and correct. Note also that the listChanged() method need not be synchronized. The ListEventPublisher ensures it is called serially.Hope this helps, James PS: I'm glad to see that the Nebula people designed their stuff correctly and used indexes to refer to table elements, rather than objects. this is a major design flaw in SWT's table. PPS: If there is enough support in the community for a standard binding from GL to the Nebula Grid Widget, we could add a new GL extension for it, and others wouldn't have to duplicate this code you have written. On Fri, Jun 20, 2008 at 7:24 AM, Wingnut <emil.crumhorn@...> wrote: Hello everyone, |
|
|
Re: IndexOutOfBoundsException on custom table implementationWingnut wrote:
> public synchronized void listChanged(ListEvent<MyTableObject> listChanges) { > while (listChanges.next()) { > List<MyTableObject> list = listChanges.getSourceList(); > > int sourceIndex = listChanges.getIndex(); > int changeType = listChanges.getType(); > > MyTableObject obj = list.get(sourceIndex); > It looks to me like the line above is the source of your problems. When changeType is DELETE, the object at "sourceIndex" has already been deleted from "list" and therefore you cannot access it. You must maintain a separate list of objects which mirrors the EventList in order to obtain a reference to the deleted object. However, it doesn't look like you really need access to the deleted object so you may be able to fix the probably by rearranging a few things and adding and "updateItem" function in your NGridTableModel assuming that calling those functions correctly updates a separate list: public class NGridTableModel implements ListEventListener<MyTableObject> { public NGridTableModel(NGridTable parent, Grid table, EventList<MyTableObject> source, TableFormat<MyTableObject> tableFormat) { source.addListEventListener(this); } public synchronized void listChanged(ListEvent<MyTableObject> listChanges) { List<MyTableObject> list = listChanges.getSourceList(); while (listChanges.next()) { int sourceIndex = listChanges.getIndex(); int changeType = listChanges.getType(); switch (changeType) { case ListEvent.DELETE: removeItem(sourceIndex); break; case ListEvent.INSERT: final MyTableObject insert = list.get(sourceIndex); addItem(sourceIndex, insert); break; case ListEvent.UPDATE: final MyTableObject update = list.get(sourceIndex); updateItem(update, sourceIndex); break; } } table.redraw(); } } --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@... For additional commands, e-mail: users-help@... |
|
|
Re: IndexOutOfBoundsException on custom table implementationThat worked like a charm, and makes sense. Thanks!
Once I've cleaned it up a bit I'll gladly contribute it (Although ideally a Nebula Grid TableViewer implementation would be prettier than this, but it still works). Should I just post here or is there a better place submit contributed code?
|
|
|
Re: IndexOutOfBoundsException on custom table implementationPosting here is fine. By all means, clean up your implementation as much as possible. Also, testcases are quite welcome too.
James On Sun, Jun 22, 2008 at 11:24 PM, Wingnut <emil.crumhorn@...> wrote:
|
| Free Forum Powered by Nabble | Forum Help |