使用TreeViewer进行JFace数据绑定

时间:2012-06-25 10:40:40

标签: eclipse eclipse-rcp jface

我正在尝试在我的RCP应用程序中构建一个视图,该视图只包含一个TreeViewer

树可以包含文件夹或叶子,文件夹可以包含文件夹和叶子。当我将文件夹添加到根文件夹的后端数据模型时,UI会自动更新,但如果我将文件夹添加到任何分支文件夹,UI将不会自动更新。请告诉我我的代码有什么问题。

模型类:

public class TreeNode extends BindableObject {

    private Folder parent;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        super.firePropertyChange("name", this.name, this.name = name);
    }

    public Folder getParent() {
        return parent;
    }

    public void setParent(Folder parent) {
        this.parent = parent;
    }

}
public class Folder extends TreeNode {

    private List<TreeNode> children = new ArrayList<TreeNode>();

    public List<TreeNode> getChildren() {
        return children;
    }

    public void setChildren(List<TreeNode> children) {
        this.children = children;
    }

    public void add(TreeNode node){
        children.add(node);
    }

}

观点:

public class ExplorerView extends ViewPart {

    private WritableList data;
    private TreeViewer treeViewer;

    public WritableList getData() {
        return data;
    }

    public TreeViewer getViewer(){
        return treeViewer;
    }

    public ExplorerView() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public void createPartControl(Composite parent) {
        parent.setLayout(new FillLayout(SWT.HORIZONTAL));
        treeViewer = new TreeViewer(parent, SWT.BORDER);
        treeViewer.setContentProvider(new ObservableListTreeContentProvider(new ExplorerObservableFactory(), new ExploerTreeStructureAdvisor()));
        treeViewer.setLabelProvider(new ExplorerTreeLabelProvider());
        ArrayList<TreeNode> list = new ArrayList<TreeNode>();
        list.add(new ExplorerDataModel().getElements()[0]);
        data = new WritableList(list, TreeNode.class);
        treeViewer.setInput(data);
    }

    @Override
    public void setFocus() {

    }

}

ObservableFactory:

public class ExplorerObservableFactory implements IObservableFactory {

    @Override
    public IObservable createObservable(Object target) {
        System.out.println(target.getClass().getName());
        if(target instanceof WritableList){
            return (WritableList)target;
        }
        else if(target instanceof Folder){
            List<TreeNode> children = ((Folder)target).getChildren();
            return new WritableList(children, TreeNode.class);
        }
        return null;
    }

}

TreeStructureAdvisor:

public class ExploerTreeStructureAdvisor extends TreeStructureAdvisor {

    @Override
    public Object getParent(Object element) {
        return ((TreeNode)element).getParent();
    }

    @Override
    public Boolean hasChildren(Object element) {
        if(element instanceof Folder){
            return true;
        }else{
            return false;
        }
    }



}

数据:

public class ExplorerDataModel {
    public TreeNode[] getElements() {
        Folder f1 = new Folder();
        f1.setName("Database Connections");
        Folder f11 = new Folder();
        f11.setName("Credit Test");
        TreeNode t1 = new TreeNode();
        t1.setName("bank@localhost");
        f11.add(t1);
        t1.setParent(f11);
        TreeNode t2 = new TreeNode();
        t2.setName("credit@localhost");
        f11.add(t2);
        t2.setParent(f11);
        Folder f12 = new Folder();
        f12.setName("Credit Product");
        TreeNode t3 = new TreeNode();
        t3.setName("nbcbcredit@localhost");
        f12.add(t3);
        t3.setParent(f12);
        TreeNode t4 = new TreeNode();
        t4.setName("nbcbcredit_bak@localhost");
        f12.add(t4);
        t4.setParent(f12);
        f1.add(f11);
        f11.setParent(f1);
        f1.add(f12);
        f12.setParent(f1);
        return new TreeNode[] { f1 };
    }
}

测试命令处理程序:

public Object execute(ExecutionEvent event) throws ExecutionException {
    ExplorerView v =(ExplorerView) HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().findView("com.amarsoft.dmp.explorer.explorerView");
        Folder f = new Folder();
        f.setName("ODA Flat Files");
        v.getData().add(f);

        Folder f1 = (Folder) v.getData().get(0);
        f1.setName("Database Connections (3)");

        Folder f2 = new Folder();
        f2.setName("Report Test");
        f1.add(f2);

        return null;
    }

如果执行上述命令,添加的文件夹“ODA Flat Files”将立即出现在树中,但添加的文件夹“Report Test”将不在那里,如果调用TreeViewer#refresh()一切正常,但是我想知道原因。

3 个答案:

答案 0 :(得分:4)

修改模型不会通知您的树。刷新是告诉树数据已更改且需要更新的一种方法。如果你在eclipse中浏览java doc for jface viewers,你会发现以下引用

  

要处理结构更改,请改用刷新方法。

答案 1 :(得分:2)

您似乎错误配置了数据绑定...

查看官方摘要:

玩得开心! (没有任何刷新;-))

PS。对于EMF,请看一下:http://tomsondev.bestsolution.at/2009/06/08/galileo-emf-databinding-%E2%80%93-part-3/

答案 2 :(得分:1)

ExplorerObservableFactory替换

... else if(target instanceof Folder){
            List<TreeNode> children = ((Folder)target).getChildren();
            return new WritableList(children, TreeNode.class);
     }

通过以下

     else if(target instanceof Folder){                
            return BeansObservables.observeList(target, "children");
     }

如果你在这里返回WritableList,则会在其上注册contentProvider的监听器(它应该在Folder bean上注册)