views:

107

answers:

4

I have a JTable which is bound to my EventTracker bean, essentially a wrapper around a list which I will use as append/clear only (i.e., a simple log). Problem is, when I add entries to the list and try to fire an event I don't see any changes. I'm using the NetBeans IDE.

The EventTracker bean is added to the view and instantiated as eventTracker1. From there, I right click on the table and choose 'Table Contents...'. Table model is bound to eventTracker1, binding expression is '${eventList}'. The columns are set up properly to operate on the entries in eventList.

// From inside EventTracker.java
public static final String EVENT_LIST_PROPERTY = "eventList"; 
public List getEventList() {
    System.out.println("Handing out eventList with size: " + Integer.toString(eventList.size()));
    return eventList;
}

public void setEventList(List incomingList) {
    List oldList = eventList;
    eventList = new ArrayList(incomingList);
    propertySupport.firePropertyChange(EVENT_LIST_PROPERTY, oldList, eventList);
}

The method firePropertyChange seems to fit the specSo when my outside code operates on setEventList, it seems to fire off the event because then getEventList is called and the list size is going up as expected. It's just that the table isn't rendering. What can I do to make this work?

+1  A: 

Assuming your data model derives from AbstractTableModel, you can update your model explicitly and fire the appropriate update method implemented in the abstract parent. Moreover, updates must occur on the EDT, typically using invokeLater(). See also Listening for Data Changes and Firing Data Change Events.

EventQueue.invokeLater(new Runnable() {

    @Override
    public void run() {
        // update model; fire appropriate update
    }
});
trashgod
A: 

you need to tell the table that the datamodel changed:

.fireTableDataChanged()

is the correct method; assuming that your table descends from the Abstract Table Model.

(so yes, I agree with trashgod)

Jill Renee
+1  A: 

I was really intent on getting the data binding working. The answers recommended were good reading, but would have led me to writing a lot of code. I didn't want to handle giving the row count/column count logic and all that extra work. As a result, this solution may provide less control but it's pretty quick and easy for this read-only workflow.

The document at http://swinglabs.org/docs/presentations/2007/DesktopMatters/beans-binding-talk.pdf gave me the skinny. The trick was to use ObservableCollection / ObservableList(new ArrayList<Event>) as the datastore. Whenever I add another entry it is automatically reflected in the JTable.

Great!

derdewey
A: 

It's not clear how you are binding the the EventTracker class to the table.I'm assuming you are using a corresponding editor and renderer class and then setting the render and editor like this table.setDefaultRenderer(EventTracker.class,new EventTrackerRender()); and table.setDefaultEditor(EventTracker.class,new EventTrackerEditor());.Editor is used in case only if you need to change the EventTracker bean through the table.

If it done from outside the table (ie.through code) override the setValueAt function in the Table model and then get the EventTracker Object(which is the current object) using getValueAt and make necessary changes (if Eventtracker is mutable object).In case of immutable object make a new object of EventTracker and set it to the object array.After this you should either call fireTableDataChanged() which is going to repaint the whole table or call fireTableCellUpdated(row,col) for a particular cell to be rendered again.

Emil