GWT - 在 celltree 中添加和删除节点

标签 gwt add

在这里,我有一个完整且非常简单的示例来动态添加/删除
单元格树的节点。我的例子效果不佳。好像有
是刷新问题。只有关闭/展开节点才会显示正确的
结果。我也没有在这个论坛中找到任何适合这个问题的答案。
也许有人可以试试我的例子并告诉我问题出在哪里。
任何其他提示也非常感谢。

问候, 马可

import java.util.ArrayList;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.gwt.view.client.TreeViewModel;

public class MyCelltreeTest implements EntryPoint {
  private AbsolutePanel absolutePanel;
  private CellTree cellTree;
  private Button btnAdd;
  private Button btnRemove;
  private MyTreeModel myTreeModel;
  private SingleSelectionModel<MyNode> selectionModelCellTree = null;

  @Override
  public void onModuleLoad() {
    RootPanel rootPanel = RootPanel.get();
    rootPanel.add(getAbsolutePanel(), 0, 0);
  }

  private AbsolutePanel getAbsolutePanel() {
    if (absolutePanel == null) {
      absolutePanel = new AbsolutePanel();
      absolutePanel.setSize("612px", "482px");
      absolutePanel.add(getCellTree(), 0, 0);
      absolutePanel.add(getBtnAdd(), 265, 428);
      absolutePanel.add(getBtnRemove(), 336, 428);
    }
    return absolutePanel;
  }

  private CellTree getCellTree() {
    if (cellTree == null) {
      myTreeModel = new MyTreeModel();
      cellTree = new CellTree(myTreeModel, null);
      cellTree.setSize("285px", "401px");
    }
    return cellTree;
  }

  private Button getBtnAdd() {
    if (btnAdd == null) {
      btnAdd = new Button("Add");
      btnAdd.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {

          MyNode node =   selectionModelCellTree.getSelectedObject();
          if(node != null)
            myTreeModel.addNew(node, "Bla");
        }
      });
    }
    return btnAdd;
  }

  private Button getBtnRemove() {
    if (btnRemove == null) {
      btnRemove = new Button("Remove");
      btnRemove.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
          MyNode node = selectionModelCellTree.getSelectedObject();
          if(node != null)
            myTreeModel.remove(node);
        }
      });
    }
    return btnRemove;
  }

  public class MyNode {
    private String name;
    private ArrayList<MyNode> childs; //nodes childrens
    private MyNode parent; //track internal parent
    private MyCell cell; //for refresh - reference to visual component

    public MyNode(String name) {
      super();
      parent = null;
      this.name = name;
      childs = new ArrayList<MyNode>();
    }

    public void addSubMenu(MyNode m) {
      m.parent = this;
      childs.add(m);
    }

    public void removeMenu(MyNode m) {

      m.getParent().childs.remove(m);
    }

    public boolean hasChildrens() {
      return childs.size()>0;
    }

    public ArrayList<MyNode> getList() {
      return childs;
    }

    public MyNode getParent() {
      return parent;
    }

    public void setCell(MyCell cell) {
      this.cell = cell;
    }

    public void refresh() {
      if(parent!=null) {
        parent.refresh();
      }
      if (cell!=null) {
        cell.refresh(); //refresh tree
      }
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }
  }

  public class MyTreeModel implements TreeViewModel {
    private MyNode officialRoot; //default not dynamic
    private MyNode studentRoot; //default not dynamic
    private MyNode testRoot; //default not dynamic
    private MyNode root;

    public MyNode getRoot() { // to set CellTree root
      return root;
    }

    public MyTreeModel() {
      selectionModelCellTree = new SingleSelectionModel<MyNode>();
      root = new MyNode("root");
      // Default items
      officialRoot = new MyNode("Cat"); //some basic static data
      studentRoot = new MyNode("Dog");
      testRoot = new MyNode("Fish");
      root.addSubMenu(officialRoot);
      root.addSubMenu(studentRoot);
      root.addSubMenu(testRoot);
    }

    //example of add add logic
    public void addNew(MyNode myparent, String name) {
      myparent.addSubMenu(new MyNode(name));
      myparent.refresh(); //HERE refresh tree
    }
    public void remove(MyNode objToRemove) {

      objToRemove.removeMenu(objToRemove);
      objToRemove.refresh();
    }

    @Override
    public <T> NodeInfo<?> getNodeInfo(T value) {
      ListDataProvider<MyNode> dataProvider;
      MyNode myValue = null;
      if (value == null) { // root is not set
        dataProvider = new ListDataProvider<MyNode>(root.getList());
      } else {
        myValue = (MyNode) value;
        dataProvider = new ListDataProvider<MyNode>(myValue.getList());
      }
      MyCell cell = new MyCell(dataProvider); //HERE Add reference
      if (myValue != null)
        myValue.setCell(cell);
      return new DefaultNodeInfo<MyNode>(dataProvider, cell, selectionModelCellTree, null);
    }

    @Override
    public boolean isLeaf(Object value) {
      if (value instanceof MyNode) {
        MyNode t = (MyNode) value;
        if (!t.hasChildrens())
          return true;
        return false;
      }
      return false;
    }
  }

  public class MyCell extends AbstractCell<MyNode> {
    ListDataProvider<MyNode> dataProvider; //for refresh

    public MyCell(ListDataProvider<MyNode> dataProvider) {
      super();
      this.dataProvider = dataProvider;
    }
    public void refresh() {
      dataProvider.refresh();
    }

    @Override
    public void render(Context context, MyNode value, SafeHtmlBuilder sb) {
      if (value == null) {
        return;
      }
      sb.appendEscaped(value.getName());
    }
  }
}

感谢 Ümit 的解释。
我尝试了关闭重新打开版本。
我已经用下面的方法替换了我的刷新方法。
添加有效,但删除无效。
整个话题很奇怪。我很惊讶这些基本的
GWT 并不真正支持函数。
有人可以给我更多帮助来运行一个真正的工作示例。
    public void refresh() {

         closeReopenTreeNodes(cellTree.getRootTreeNode());
    }

    private void closeReopenTreeNodes(TreeNode node) {
        if(node == null) {
            return;
        }
        for(int i = 0; i < node.getChildCount(); i++) {

             if(node.getChildValue(i).equals(this)){

                 if(node.getParent() != null){

                     node.getParent().setChildOpen(i, false);
                     //node.getParent().setChildOpen(i, true);
                 }

                 node.setChildOpen(i, false);
                 node.setChildOpen(i, true);
             }               
             TreeNode child = node.setChildOpen(i, node.isChildOpen(i));
             closeReopenTreeNodes(child);
        }
    }

这是我的第三次尝试:
这种方式是 gwt-commiter 推荐的。
请看以下问题:
http://code.google.com/p/google-web-toolkit/issues/detail?id=7160

当前状态:
* 添加是可能的
* 如果不是最后一个 child ,删除是可能的!

所以,最后一个打开点,如果最后一个打开的 child 刷新树!
package com.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.gwt.view.client.TreeViewModel;

public class MyCelltreeTest2 implements EntryPoint {
    private AbsolutePanel absolutePanel;
    private CellTree cellTree;
    private Button btnAdd;
    private Button btnRemove;
    private MyTreeModel myTreeModel;
    private SingleSelectionModel<MyNode> selectionModelCellTree = null;
    private Map<MyNode, ListDataProvider<MyNode>> mapDataProviders = null;
    private ListDataProvider<MyNode> rootDataProvider = null;

    public void onModuleLoad() {
            RootPanel rootPanel = RootPanel.get();
            rootPanel.add(getAbsolutePanel(), 0, 0);
    }

    private AbsolutePanel getAbsolutePanel() {
            if (absolutePanel == null) {
                    absolutePanel = new AbsolutePanel();
                    absolutePanel.setSize("612px", "482px");
                    absolutePanel.add(getCellTree(), 0, 0);
                    absolutePanel.add(getBtnAdd(), 265, 428);
                    absolutePanel.add(getBtnRemove(), 336, 428);
            }
            return absolutePanel;
    }
    private CellTree getCellTree() {
            if (cellTree == null) {
                    myTreeModel = new MyTreeModel();
                    cellTree = new CellTree(myTreeModel, null);
                    cellTree.setSize("285px", "401px");
            }
            return cellTree;
    }
    private Button getBtnAdd() {
            if (btnAdd == null) {
                    btnAdd = new Button("Add");
                    btnAdd.addClickHandler(new ClickHandler() {
                            public void onClick(ClickEvent event) {

                    MyNode node = selectionModelCellTree.getSelectedObject();

                                 myTreeModel.add(node, "Bla");
                            }
                    });
            }
            return btnAdd;
    }
    private Button getBtnRemove() {
            if (btnRemove == null) {
                    btnRemove = new Button("Remove");
                    btnRemove.addClickHandler(new ClickHandler() {
                            public void onClick(ClickEvent event) {

                             MyNode node = selectionModelCellTree.getSelectedObject();

                                     myTreeModel.remove(node);
                            }
                    });
            }
            return btnRemove;
    }


    public class MyNode {

        private String name;
        private ArrayList<MyNode> childs; //nodes childrens
        private MyNode parent; //track internal parent


        public MyNode(String name) {
            super();
            parent = null;
            this.name = name;
            childs = new ArrayList<MyNode>();
        }
        public boolean hasChildrens() {
            return childs.size()>0;
        }
        public ArrayList<MyNode> getList() {
            return childs;
        }
        public MyNode getParent() {
            return parent;
        }

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }      
    }

    public class MyTreeModel implements TreeViewModel {


        public MyTreeModel() {
            selectionModelCellTree = new SingleSelectionModel<MyNode>();
            mapDataProviders = new HashMap<MyCelltreeTest2.MyNode, ListDataProvider<MyNode>>();
        }

        public void add(MyNode myparent, String name) {

            MyNode child = new MyNode(name);

            //root-node
            if(myparent == null){
                    rootDataProvider.getList().add(child);
                    mapDataProviders.put(child, rootDataProvider);
            }
            else{

                    ListDataProvider<MyNode> dataprovider = mapDataProviders.get(myparent);
                    myparent.childs.add(child);
                    child.parent = myparent;
                    dataprovider.refresh();
            }
        }   
        public void remove(MyNode objToRemove) {

            ListDataProvider<MyNode> dataprovider = mapDataProviders.get(objToRemove);
                    dataprovider.getList().remove(objToRemove);
  //                 mapDataProviders.remove(objToRemove);
                    dataprovider.refresh();
                    dataprovider.flush();

                    if(objToRemove.parent != null){
                            ListDataProvider<MyNode> dataproviderParent = mapDataProviders.get(objToRemove.parent);
                            objToRemove.parent.childs.remove(objToRemove);
                            dataproviderParent.refresh();
                            dataproviderParent.flush();
                    }
                    else{
                            rootDataProvider.refresh();
                            rootDataProvider.flush();
                    }       
        } 


        @Override
        public <T> NodeInfo<?> getNodeInfo(T value) {

            if (value == null) { // root is not set
             rootDataProvider = new ListDataProvider<MyNode>(new ArrayList<MyNode>());
                    MyCell cell = new MyCell(); 
   return new DefaultNodeInfo<MyNode>(rootDataProvider, cell,   
  selectionModelCellTree, null);
            } else {
                    MyNode myValue = (MyNode) value;
                ListDataProvider<MyNode> dataProvider = 
                    new ListDataProvider<MyNode>(myValue.childs);
                    MyCell cell = new MyCell(); 
                    for(MyNode currentNode : myValue.childs){
                            mapDataProviders.put(currentNode, dataProvider);
                    }
                return new DefaultNodeInfo<MyNode>(dataProvider, cell,  
              selectionModelCellTree, null);
            }
        }

        @Override
        public boolean isLeaf(Object value) {
            if (value instanceof MyNode) {
                MyNode t = (MyNode) value;
                if (!t.hasChildrens())
                    return true;
                return false;
            }
            return false; 
        }

    }

    public class MyCell extends AbstractCell<MyNode> {
            public MyCell() {
              super();
            }
            @Override
            public void render(Context context, MyNode value, SafeHtmlBuilder sb) {
              if (value == null) {
                return;
              }
              sb.appendEscaped(value.getName());
            }
    }
}

最佳答案

这在某种程度上是 CellTree 的一个已知问题。
刷新问题的原因是在getNodeInfo()函数你新建ListDataProvider每个 CellTree 级别的实例。
如果您更新 ListDataProvider 中的项目,CellTree 只会更新/刷新自身。 .
我相信您的 removeMenu() 和 addSubMenu() 函数从存储在 MyNode 类中的原始列表中添加和删除项目,但不会更新相应 ListDataProviders 中的列表(您可以尝试在 Debug模式下检查)。
关闭再重新刷新CellTree的原因
-打开节点是因为当您重新打开节点时getNodeInfo()被再次调用,整个 CellTree 结构将被再次构造(分别包括新菜单或不包括删除的菜单)。

有两种可能的解决方案:

  • 保留每个 ListDataProviders 的引用某处并在该列表上调用 remove/add (尽管您这样做了,但我认为这些项目并未真正在那里添加/删除)。
  • 以编程方式关闭所有节点并重新打开它。

  • 两者都是要实现的 PITA。不幸的是,没有简单的方法可以解决它。

    关于GWT - 在 celltree 中添加和删除节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9044688/

    相关文章:

    gwt - 拦截标签小部件上的点击

    eclipse - 为什么我的 UiProperty 在 GWT 设计器中不再可编辑?

    c# - 在c#中添加数字

    javascript - 在滚动时将类添加到 <li> 元素内的链接

    php - wordpress 中的 add_action 函数

    java - 快速开发基于 GWT-EJB 的应用程序的方法

    java - 用相似的列值给网格着色

    java - GWT 无法在现有元素上定义 Canvas

    java - Android ArrayList Calendar 添加和获取不同

    android - 如何将项目添加到 Spinner 的 ArrayAdapter?