我的Eclipse RCP应用程序中有一个虚拟表。我们调用后端以检索要在虚拟表中填充的数据。
我们希望在表格的默认列上进行单列排序。我们使用ViewerComparator来实现排序功能。我的问题是,当表第一次加载数据时,我无法进行这种排序。但是,当我单击该列时,一切正常。
这就是我将比较器设置为列的方式
TableViewerColumn tvc = viewer.addColumn(100, SWT.LEFT, "Name");
viewer.setColumnComparator(tvc,
new Comparator<Person>() {
@Override
public int compare(Person o1,Person o2) {
double firstValue = Double.parseDouble(o1
.getAge());
double secondValue = Double.parseDouble(o2
.getAge());
return firstValue > secondValue ? 1 : -1;
}
});
自定义查看器中的setColumnComparator方法
public void setColumnComparator(TableViewerColumn tvc, Comparator<T> cmp){
final MyViewerComparator c = new MyViewerComparator(cmp);
final TableColumn tc = tvc.getColumn();
setComparator(c);
getTable().setSortDirection(c.getDirection());
getTable().setSortColumn(tc);
refresh();
tc.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
<same code as above>
}
});
MyViewerComparator
class MyViewerComparator extends ViewerComparator{
Comparator<T> cmp;
boolean desc = true;
MyViewerComparator(Comparator<T> cmp){
this.cmp = cmp;
}
int getDirection(){
return desc?SWT.UP:SWT.DOWN;
}
void flipDirection(){
desc = !desc;
}
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
if(e1 == null || e2 == null){
return 0;
}
int rc = cmp.compare((T)e1, (T)e2);
if(desc)
return -rc;
return rc;
}
}
当表第一次加载数据时,它进入上述代码中的Bolded条件内部,因为其中一个对象始终为NULL
注意:如果我使用标准表而不是虚拟表,则此功能可以正常工作。我不确定是否可以将其更改为使用标准表,因为我们也需要延迟加载功能。
使用的ContentProvider是:ObservableListContentProvider
请指教..
最佳答案
希望可以对其他人有所帮助的最新答案。将SWT.VIRTUAL与ObservableListContentProvider结合使用时遇到完全相同的问题。
SWT.VIRTUAL的原始意图是,不需要提取内容中的所有元素以仅显示部分内容。需要实现一个自定义的内容提供者,该提供者仅需返回当前需要在屏幕上显示的元素。您还必须告诉表存在的元素总数。在这种用例中,无法使用ViewerComparator以常规方式对表进行排序,因为并非所有元素都已知。但是,SWT.VIRTUAL也可以用作性能优化,以呈现具有许多元素的表。这对于不可观察的ArrayContentProvider似乎可以正常工作。
但是,当使用ObservableListContentProvider时,出现的问题与您完全相同。它以某种方式设法变得聪明,仅更新实际已更改的元素。在实现的最深处,虚拟表出了点问题,我不知道到底是什么。但是我有一个解决方案:根本不使用ObservableListContentProvider,而只是刷新表查看器。您可以例如使用普通的ArrayContentProvider并将以下侦听器添加到查看器的IObservableList内容中:
new IListChangeListener() {
@Override
public void handleListChange(ListChangeEvent event) {
viewer.refresh();
}
};
实际上,我实际上实现了自己的“ SimpleObservableListContentProvider”,该操作确实做到了这一点,但还通过实现inputChanged方法从旧的输入列表中删除此侦听器并将其添加到新的输入列表中,来切换表的输入。