发新话题
打印

dwt2 ILazyTreePathContentProvider使用实例

在GUI编程中,Tree是最常用的控件之一。如果TreeItem比较多,比如数百上千个,在程序启动时全部进行初始化,会影响程序启动效率,从而降低用户的体验。我原来就遇到过这个问题,一直没有好的解决办法。

在Java swt Jface中,这个问题得到了较好的解决,就是使用ILazyTreeContentProvider,TreeItem在展开时才创建。

但是如果Tree的数据如果从数据库读取,ILazyTreeContentProvider也会有问题。因为IO是非常耗时的操作。

举例来说,有10个根TreeItem, 每个TreeItem下又有15个子TreeItem。
程序启动时,读取要创建10个根TreeItem所需要的数据。Jface在更新每个TreeItem时,又会请求每个根TreeItem的childCount, 于是又要读取一次数据库。这样在程序启动时就要读取11次数据库,很是影响速度。

解决办法:

1. 在数据库表中增加chidCount列,在程序启动第一次读取数据库时,根据这个列值是否大于0,就知道了每个根TreeItem是否有子TreeItem

2. 同时还要使用ILazyTreePathContentProvider

于是找ILazyTreePathContentProvider的sample, 奇怪的是Jface这么红,却没有在Google搜索到使用的例子。只好去读源代码自己研究。。。。于是就有了下面示例代码。要注意下面只是示例用法,代码并不全,有些函数没有给出实现代码,理解其用意就可以了。

经过这样的改进,程序启动时,TreeItem项再多,程序启动的速度也很快了。

java swt, jface 虽然比较复杂。复杂不要紧,关键是需要的功能能否实现。
复制内容到剪贴板
代码:
// Written in the D programming language.

/*******************************************************************************
        
        Copyright:      Copyright (c) 2009  (dyuyan  gmail at com) All rights reserved

        License:        BSD style: $(LICENSE)

        Version:        Initial release: May 2009

        Authors:        紫气东来 ( D Programming Language China : http://www.d-programming-language-china.org/ )

*******************************************************************************/


import org.eclipse.jface.viewers.ILazyTreePathContentProvider;
import tango.util.Convert;
debug import tango.io.Stdout;

class TreeContentProvider : ILazyTreePathContentProvider {
    public static GuiNode rootNode;   
    private TreeViewer viewer;
        
    private static TreeContentProvider instance;
    public static TreeContentProvider getInstance() { return instance; }
        
    public this(TreeViewer viewer) {
        this.viewer = viewer;
        this.instance = this;
    }
    public static GuiNode getRootNode() { return rootNode; }   
    //IContentProvider
    public void dispose() { }
    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        this.rootNode = cast(GuiNode) newInput;
    }

    //ILazyTreePathContentProvider
    //#2 调用
    public void updateElement(TreePath parentPath, int index)
    {
        GuiNode node = (parentPath.getSegmentCount == 0) ?
            rootNode :
            cast(GuiNode) parentPath.getLastSegment();
        
        debug Stdout.formatln("upadeElement in: {} {}", node.toString, index);
        
        if(index < node.getChildren(true).length) // getChildren(true) to read data from database if necessary
        {
            TreePath element = parentPath.createChildPath(node.getChildren(false)[index]);
            viewer.replace(parentPath, index, node.getChildren(false)[index]);
            updateHasChildren(element); //important statement
            //updateChildCount(element, -1); //
        }  
        else
        { assert(0); }
        
        debug Stdout.formatln("updateElement out: {} {}", node.toString, index);
    }
   
    //#1  setInput referesh,click + to expand TreeItem
    //
    public void updateChildCount(TreePath treePath, int currentChildCount) {        
        GuiNode node = (treePath.getSegmentCount == 0) ?
            rootNode :
            cast(GuiNode) treePath.getLastSegment();
        
        debug Stdout.formatln("updateChildCount in: {}", node.toString);
                    
        int childCount = node.childCount();  //read childCount from database if necessary
        if(childCount != currentChildCount)
            //viewer.setChildCount(treePath, childCount);  //dwt2 bug here?
            viewer.setChildCount(node, childCount);         
        debug Stdout.formatln("updateChildCount out: {}", node.toString);        
    }
   
    public void updateHasChildren(TreePath path)
    {
        auto node = cast(GuiNode) path.getLastSegment();
        debug Stdout.formatln("updateHasChildren in: {}", node.toString);                    
        int postCount = to!(int)(nodeGetChildrenCount(node), 0); //read a column value from memory
        
        if(postCount > 0) //we know the item has children
        {
            //debug Stdout.formatln("{} hasChildren {}", node.toString, postCount);
            viewer.setHasChildren(path, true);
        }
        else
        {
            viewer.setHasChildren(path, node.childCount() > 0); // read from database
            //debug Stdout.formatln("{} childCount {}", node.toString, node.childCount());
        }
        debug Stdout.formatln("updateHasChildren out: {}", node.toString);
        
    }
   
    public TreePath[] getParents(Object element) {
        debug Stdout.formatln("getParents in");
        
        TreePath[] result;
        if(auto node = cast(GuiNode)element)
        {
            GuiNode[] nodes;        
            while(node.parent !is null)
            {
                node = node.parent;
                nodes ~= node;
            }
            if(nodes.length > 1) //TreePath not contains rootNode
                result = [new TreePath(nodes.reverse[1..$])];            
        }
        debug Stdout.formatln("updateParents out");        
        return result;
    }   
}

TOP

发新话题