JFace TableViewer должен реагировать на изменение списка

У нас есть следующий сценарий: RCP-приложение Eclipse 4 должно записать вывод журнала. Эти журналы связаны через OSGi-Service и должны отображаться с помощью JFace TableViewer.

Это хорошо работает для первого запуска этой ViewPart. (потому что логи уже есть) Если другой плагин пишет логи после запуска представления, то и это представление следует обновить. ArrayList, содержащий журналы для представления (как часть модели), обновляется правильно.

Таблица устроена так:

@PostConstruct 

public void createControls(Composite parent) {
    b = new TableViewerBuilder(parent);
    b.createColumn("Datum").bindToProperty("time").build();
    b.createColumn("Message").bindToProperty("message").build();
    b.createColumn("Level").bindToProperty("level").build();
    b.createColumn("Bundle").bindToProperty("bundle").build();
    m_bindingContext = initDataBindings();
}

Привязка данных делается так:

protected DataBindingContext initDataBindings() {
    DataBindingContext bindingContext = new DataBindingContext();
    input = new WritableList(logItemList.getItems(), LogItem.class);
    ViewerSupport.bind(tableViewer, input, BeanProperties
        .values(new String[] { "time", "message", "level" }));
    return bindingContext;

}

Мы получаем элементы из списка (который корректно обновляется) и помещаем их в WritableList. Этот список привязан к TableViewer и отображает метку времени, сообщение и какой-то уровень журнала.

LogItemList настроен следующим образом:

public class LogItemList extends ModelObject {
     [.. stuff ..]
    private List<LogItem> items;

    public List<LogItem> getItems() {
        return items;
    }
    public void addItem(LoggingItem item) {
        LogItem logItem = new LogItem(item);
        List<LogItem> tmp = items;
        items.add(logItem);

        firePropertyChange("items", tmp, items);
    }
}

firePropertyChange-Метод унаследован от ModelObject-класса.

    public class ModelObject {
        private PropertyChangeSupport changeSupport = 
             new PropertyChangeSupport(this);
        protected void firePropertyChange(String propertyName, 
            Object oldValue,
            Object newValue) {
          changeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

Я думал, что TableViewer/Databinding реагирует на это событие изменения, но это не так.

У кого-нибудь есть идеи, как это сделать правильно?

Заранее спасибо, Стеффен


person Steffen    schedule 01.03.2013    source источник


Ответы (1)


WritableList не отслеживает список автоматически. (Как это может быть, поскольку List не имеет интерфейса уведомлений?)

Самый простой выход — реализовать LogItemList.items с WriteableList вместо ArrayList. Недостатком является то, что базовая модель не так чиста, как могла бы/должна быть в противном случае.

Кроме того, вы можете добавить прослушиватель к вашему LogItemList, который распространяется на WritableList.fireListChanged(...). Возможно, это «более чистое» решение, но немного больше работы, так как вам нужно создать подкласс «WritableList».

Или вы можете реализовать базовую модель с точки зрения EMF и использовать EMFObservables.observeList(...). Намного больше работы, но на самом деле так, я бы сделал это :-)

person Tonny Madsen    schedule 04.03.2013
comment
Спасибо за ваш ответ. Мы немного изменили код и удалили DataBindingContext. Теперь мы просто создаем столбцы с помощью TableBuilder от Ральфа Эберта. Метод bindToProperty() выполняет свою работу. Если в LogItemList добавляется новый элемент, мы запускаем событие propertyChangeEvent, и с помощью метода TableBuilder.setInput() содержимое загружается в таблицу. Привет, Штеффен - person Steffen; 20.03.2013