2012-01-28 29 views
8

Ở đây tôi có một ví dụ hoàn chỉnh và rất dễ dàng để tự động thêm/xóa các nút vào một ô. Ví dụ của tôi không hoạt động tốt. Dường như có là sự cố làm mới. Chỉ đóng/mở rộng các nút sẽ hiển thị kết quả chính xác. Tôi cũng không tìm thấy câu trả lời nào trong diễn đàn này phù hợp với vấn đề này. Có thể ai đó có thể thử ví dụ của tôi và cho tôi biết vấn đề ở đâu. Bất kỳ gợi ý nào khác cũng rất được đánh giá cao.GWT - Thêm và xóa các nút trong celltree

Greetings, Marco

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()); 
    } 
    } 
} 

Cảm ơn Ümit cho lời giải thích của bạn. Tôi đã thử phiên bản mở lại. Tôi đã thay thế phương thức làm mới bằng các phương thức bên dưới. Thêm đang hoạt động nhưng không xóa. Rất lạ cả chủ đề. Tôi rất ngạc nhiên khi các chức năng cơ bản này không thực sự được hỗ trợ bởi GWT. Ai đó có thể giúp tôi nhiều hơn để chạy một ví dụ làm việc thực sự.

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); 
     } 
    } 

Đây là lần thử thứ ba của tôi: Cách này được khuyến nghị bởi gwt-commiter. Xin xem sau phát hành: http://code.google.com/p/google-web-toolkit/issues/detail?id=7160

tình trạng hiện tại: * Thêm thể * Loại bỏ là có thể nếu không phải là con cuối cùng!

Vì vậy, điểm mở cuối cùng, hãy làm mới cây nếu con cuối cùng mở!

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()); 
      } 
    } 
} 
+0

Có ai đã dọn đường sạch sẽ không? Bực bội việc này đã bị đóng như được thiết kế trong nhà phát hành GWT - http://code.google.com/p/google-web-toolkit/issues/detail?id=7160 – SSR

Trả lời

5

Đây là một vấn đề được biết đến với CellTree.
Lý do cho sự cố làm mới là ở hàm getNodeInfo() bạn tạo một phiên bản ListDataProvider mới cho từng cấp CellTree.
CellTree chỉ cập nhật/tự làm mới nếu bạn cập nhật các mục trong đó ListDataProvider. Tôi tin rằng các hàm removeMenu() và addSubMenu() của bạn thêm và xóa các mục khỏi danh sách gốc được lưu trữ trong lớp MyNode của bạn nhưng sẽ không cập nhật danh sách trong ListDataProviders tương ứng (bạn có thể thử kiểm tra trong chế độ gỡ lỗi).
Lý do tại sao CellTree được làm mới khi bạn đóng và lại -open các nút là bởi vì khi bạn mở lại các nút, getNodeInfo() được gọi lại và toàn bộ cấu trúc CellTree sẽ được xây dựng lại (bao gồm menu mới hoặc không có loại bỏ một tương ứng).

Có hai giải pháp khả thi:

  1. Giữ một tài liệu tham khảo cho mỗi ListDataProviders đâu đó và gọi xóa/thêm vào danh sách đó (mặc dù bạn làm điều đó tôi giả định rằng mục này không thực sự thêm/bớt có).
  2. Lập trình đóng tất cả các nút và mở lại.

Cả hai bằng cách nào đó là PITA để triển khai. Thật không may là không có cách nào dễ dàng xung quanh nó.

+0

Cảm ơn bạn đã giải thích. Tôi đã thử phiên bản mở lại gần. Thêm đang hoạt động nhưng không xóa. Bạn có một ví dụ làm việc hoàn chỉnh cho một trong các giải pháp được đề xuất của bạn? – user1165474

+0

Tôi sẽ đăng mã mở lại vào ngày mai hoặc ngày thứ sau ngày mai –

+0

Xin chào, bạn có ví dụ không? Tôi vẫn chưa tìm ra giải pháp nào cho điều đó. – user1165474

0

Tôi chỉ xóa mảng đối tượng được duy trì trong nhà cung cấp dữ liệu của mình. Tôi làm điều này trong onRangeChanged(final HasData<?> display).Tôi đoán tôi không sử dụng một số ListDataProvider ở đây, thay vào đó, tôi sử dụng một cái gì đó mở rộng AbstractDataProvider<T>.

Để thêm nút, hãy thêm nút đó vào danh sách của bạn trong phương thức onRangeChanged() và sau đó gọi updateRowData(). Bạn cũng có thể làm điều này để xóa.

0

Tôi nghĩ rằng tôi có thể liếm vấn đề ...

Về cơ bản tôi đã mở rộng và lớp con nhiều nơi trên CellTree và đã thu được một ví dụ làm việc gần như hoàn hảo. Quá phức tạp để ghi lại ở đây, nhưng đủ để nói giải pháp liên quan đến việc sử dụng một lớp nút mà tôi đã lưu trữ nhà cung cấp dữ liệu trong mỗi nút.

https://code.google.com/p/updatable-cell-tree/

+0

Trong khi liên kết này có thể trả lời câu hỏi, thì tốt hơn nên đưa các phần quan trọng của câu trả lời vào đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở thành không hợp lệ nếu trang được liên kết thay đổi. – chris

+0

Công bằng đủ, nhưng không thực sự thực tế nếu bạn dành thời gian để thực sự nhìn vào câu trả lời. Giải pháp không phải là một cái gì đó đơn giản, đủ để bao gồm ở đây yeah? – gslender

Các vấn đề liên quan