What is the right way to update a table view in a

2019-08-04 11:43发布

问题:

Say I have a ItemListPart class in my RCP project, and there is a table to be displayed in it as following:

import java.util.List;

import javax.annotation.PostConstruct;

import org.eclipse.e4.ui.di.Focus;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

public class ItemListPart {
    private Table table;

    @PostConstruct 
    public void createControls(Composite parent){
      //I wish the ItemList could be changed from outside the ItemListPart class.
      List<Item> ItemList = getItemList();

      parent.setLayout(new GridLayout(2, false));

      table = new Table(parent, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
      table.setLinesVisible(true);
      table.setHeaderVisible(true);
      GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
      data.heightHint = 200;
      table.setLayoutData(data);

      String[] titles = { "Item Name", "Description"};
      for (int i = 0; i < titles.length; i++) {
          TableColumn column = new TableColumn(table, SWT.NONE);
          column.setText(titles[i]);
          table.getColumn(i).pack();
      }


      for(Item it:ItemList){
          TableItem item = new TableItem(table, SWT.NONE);
          item.setText(0, it.getName());
          item.setText(1, it.getDesc());
      }

      for (int i=0; i<titles.length; i++) {
          table.getColumn (i).pack ();
      }
    }

    @Focus
    public void onFocus() {
        table.setFocus();
    }
}

Here the ItemList<Item> is a List which I wish could be changed from outside the ItemListPart class, and whenever the data in ItemList<Item> changed, the table view could be auto refreshed according to the updated data. What is the right way to achieve this goal? Thanks.

回答1:

There is no one 'correct' way.

One way is to use the event broker and have your view part listen for events from the code which updates the list.

In the code which updates the list post an event:

@Inject
IEventBroker eventBroker;

...

eventBroker.post("/list/updated", Collections.EMPTY_MAP);

In your view listen for the update event:

@Inject
@Optional
public void listUpdated(@UIEventTopic("/list/updated") Event event)
{
  // TODO handle the update
}

Note: Event is org.osgi.service.event.Event.

You will probably find it easier to use TableViewer rather than Table as the separate content provider makes it much easier to update the table for content changes.

You can also pass data in the event using something like:

MyClass myClass = ....

eventBroker.post("/list/updated", myClass);


@Inject
@Optional
public void listUpdated(@UIEventTopic("/list/updated") MyClass myClass)

There is some more information on event brokers here