<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    精彩的人生

    好好工作,好好生活

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

    兩天前GEF發(fā)布了3.1M7版本,但使用下來發(fā)現(xiàn)和M6沒有什么區(qū)別,是不是主要為了和Eclipse版本相配套?希望3.1正式版早日發(fā)布,應(yīng)該會新增不少內(nèi)容。上一篇帖子介紹了如何實(shí)現(xiàn)表格功能,在開發(fā)過程中,另一個經(jīng)常用到的功能就是樹,雖然SWT提供了標(biāo)準(zhǔn)的樹控件,但使用它完成如組織結(jié)構(gòu)圖這樣的應(yīng)用還是不夠直觀和方便。在目前版本(3.1M7)的GEF中雖然沒有直接支持樹的實(shí)現(xiàn),但Draw2D提供的例子程序里卻有我們可以利用的代碼(org.eclipse.draw2d.examples.tree.TreeExample,運(yùn)行界面見下圖),通過它可以節(jié)約不少工作量。

    treeexample.gif
    圖1 Draw2D例子中的TreeExample

    記得數(shù)年前曾用Swing做過一個組織結(jié)構(gòu)圖的編輯工具,當(dāng)時的實(shí)現(xiàn)方式是讓畫布使用XYLayout,在適當(dāng)?shù)臅r候計算和刷新每個樹節(jié)點(diǎn)的位置,算法的思想則是深度優(yōu)先搜索,非樹葉節(jié)點(diǎn)的位置由其子節(jié)點(diǎn)的數(shù)目和位置決定。我想這應(yīng)該是比較直觀的方法吧,但是這次看了Draw2D例子里的實(shí)現(xiàn)覺得也很有道理,以前沒想到過。在這個例子里樹節(jié)點(diǎn)圖形稱為TreeBranch,它包含一個PageNode(表現(xiàn)為帶有折角的矩形)和一個透明容器contentsPane,(一個Layer,用來放置子節(jié)點(diǎn))。在一般情況下,TreeBranch本身使用名為NormalLayout的布局管理器將PageNode放在子節(jié)點(diǎn)的正上方,而contentsPane則使用名為TreeLayout的布局管理器計算每個子節(jié)點(diǎn)應(yīng)在的位置。所以我們看到的整個樹實(shí)際上是由很多層子樹疊加而成的,任何一個非葉節(jié)點(diǎn)對應(yīng)的圖形的尺寸都等于以它為根節(jié)點(diǎn)的子樹所占區(qū)域的大小。

    從這個例子里我們還看到,用戶可以選擇使用橫向或縱向組織樹(見圖2),可以壓縮各節(jié)點(diǎn)之間的空隙,每個節(jié)點(diǎn)可以橫向或縱向排列子節(jié)點(diǎn),還可以展開或收起子節(jié)點(diǎn),等等,這為我們實(shí)現(xiàn)一個方便好用的樹編輯器提供了良好的基礎(chǔ)(視圖部分的工作大大簡化了)。

    treevertical.gif
    圖2 縱向組織的樹

    這里要插一句,Draw2D例子中提供的這些類的具體內(nèi)容我沒有仔細(xì)研究,相當(dāng)于把它們當(dāng)作Draw2D API的一部分來用了(包括TreeRoot、TreeBranch、TreeLayout、BranchLayout、NormalLayout、HangingLayout、PageNode等幾個類,把代碼拷到你的項目中即可使用),因為按照GEF 3.1的計劃表,它們很有可能以某種形式出現(xiàn)在正式版的GEF 3.1里。下面介紹一下我是如何把它們轉(zhuǎn)換為GEF應(yīng)用程序的視圖部分從而實(shí)現(xiàn)樹編輯器的。

    首先從模型部分開始。因為樹是由一個個節(jié)點(diǎn)構(gòu)成的,所以模型中最主要的就是節(jié)點(diǎn)類(我稱為TreeNode),它和例子里的TreeBranch圖形相對應(yīng),它應(yīng)該至少包含nodes(子節(jié)點(diǎn)列表)和text(顯示文本)這兩個屬性;例子里有一個TreeRoot是TreeBranch的子類,用來表示根節(jié)點(diǎn),在TreeRoot里多了一些屬性,如horizontal、majorSpacing等等用來控制整個樹的外觀,所以模型里也應(yīng)該有一個繼承TreeNode的子類,而實(shí)際上這個類就應(yīng)該是編輯器的contents,它對應(yīng)的圖形TreeRoot也就是一般GEF應(yīng)用程序里的畫布,這個地方要想想清楚。同時,雖然看起來節(jié)點(diǎn)間有線連接,但這里我們并不需要Connection對象,這些線是由布局管理器繪制的,畢竟我們并不需要手動改變線的走向。所以,模型部分就是這么簡單,當(dāng)然別忘了要實(shí)現(xiàn)通知機(jī)制,下面看看都有哪些EditPart。

    與模型相對應(yīng),我們有TreeNodePart和TreeRootPart,后者和前者之間也是繼承關(guān)系。在getContentPane()方法里,要返回TreeBranch圖形所包含的contentsPane部分;在getModelChildren()方法里,要返回TreeNode的nodes屬性;在createFigure()方法里,TreeNodePart應(yīng)返回TreeBranch實(shí)例,而TreeRootPart要覆蓋這個方法,返回TreeRoot實(shí)例;另外要注意在refreshVisuals()方法里,要把模型的當(dāng)前屬性正確反映到圖形中,例如TreeNode里有反映節(jié)點(diǎn)當(dāng)前是否展開的布爾變量expanded,則refreshVisuals()方法里一定要把這個屬性的當(dāng)前值賦給圖形才可以。以下是TreeNodePart的部分代碼:

    public IFigure getContentPane() {
        
    return ((TreeBranch) getFigure()).getContentsPane();
    }


    protected List getModelChildren() {
        
    return ((TreeNode) getModel()).getNodes();
    }


    protected IFigure createFigure() {
        
    return new TreeBranch();
    }


    protected void createEditPolicies() {
        installEditPolicy(EditPolicy.COMPONENT_ROLE, 
    new TreeNodeEditPolicy());
        installEditPolicy(EditPolicy.LAYOUT_ROLE, 
    new TreeNodeLayoutEditPolicy());
        installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, 
    new ContainerHighlightEditPolicy());
    }

    上面代碼中用到了幾個EditPolicy,這里說一下它們各自的用途。實(shí)際上,從Role中已經(jīng)可以看出來,TreeNodeEditPolicy是用來負(fù)責(zé)節(jié)點(diǎn)的刪除,沒有什么特別;TreeNodeLayoutEditPolicy則復(fù)雜一些,我把它實(shí)現(xiàn)為ConstrainedLayoutEditPolicy的一個子類,并實(shí)現(xiàn)createAddCommand()和getCreateCommand()方法,分別返回改變節(jié)點(diǎn)的父節(jié)點(diǎn)和創(chuàng)建新節(jié)點(diǎn)的命令,另外我讓createChildEditPolicy()方法返回NonResizableEditPolicy的實(shí)例,并覆蓋其createSelectionHandles()方法如下,以便在用戶選中一個節(jié)點(diǎn)時用一個控制點(diǎn)表示選中狀態(tài),不用缺省邊框的原因是,邊框會將整個子樹包住,不夠美觀,并且在多選的時候界面比較混亂。

    protected List createSelectionHandles() {
        List list
    =new ArrayList();
        list.add(
    new ResizeHandle((GraphicalEditPart)getHost(), PositionConstants.NORTH));
        
    return list;
    }

    選中節(jié)點(diǎn)的效果如下圖,我根據(jù)需要改變了樹節(jié)點(diǎn)的顯示(修改PageNode類):

    treeselection.gif
    圖3 同時選中三個節(jié)點(diǎn)(Node2、Node3和Node8)

    最后一個ContainerHighlightEditPolicy的唯一作用是當(dāng)用戶拖動節(jié)點(diǎn)到另一個節(jié)點(diǎn)區(qū)域中時,加亮顯示后者,方便用戶做出是否應(yīng)該放開鼠標(biāo)的選擇。它是GraphicalEditPolicy的子類,部分代碼如下,如果你看過Logic例子的話,應(yīng)該不難發(fā)現(xiàn)這個類就是我從那里拿過來然后修改一下得到的。

    protected void showHighlight() {
        ((TreeBranch) getContainerFigure()).setSelected(
    true);
    }


    public void eraseTargetFeedback(Request request) {
        ((TreeBranch) getContainerFigure()).setSelected(
    false);
    }

    好了,現(xiàn)在樹編輯器應(yīng)該已經(jīng)能夠工作了。為了讓用戶使用更方便,你可以實(shí)現(xiàn)展開/收起子節(jié)點(diǎn)、橫向/縱向排列子節(jié)點(diǎn)等等功能,在視圖部分Draw2D的例子代碼已經(jīng)內(nèi)置了這些功能,你要做的就是給模型增加適當(dāng)?shù)膶傩浴N疫@里的一個截圖如下所示,其中Node1是收起狀態(tài),Node6縱向排列子節(jié)點(diǎn)(以節(jié)省橫向空間)。

    treeeditor.gif
    圖4 樹編輯器的運(yùn)行界面

    這個編輯器我花一天時間就完成了,但如果不是利用Draw2D的例子,相信至少要四至六天,而且缺陷會比較多,功能上也不會這么完善。我感覺在GEF中遇到?jīng)]有實(shí)現(xiàn)過的功能前最好先找一找有沒有可以利用的資源,比如GEF提供的幾個例子就很好,當(dāng)然首先要理解它們才談得上利用。


    原文地址: http://bjzhanghao.cnblogs.com/archive/2005/05/27/163277.html

    posted on 2005-12-28 16:55 hopeshared 閱讀(527) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲明星合成图综合区在线| 国产AV无码专区亚洲A∨毛片| 色多多www视频在线观看免费| 久久久久国产精品免费免费搜索 | 久久99精品免费一区二区| 国产区在线免费观看| 亚洲精品网站在线观看不卡无广告| 在线观看亚洲网站| 6080午夜一级毛片免费看6080夜福利 | 午夜寂寞在线一级观看免费| 亚洲最大av资源站无码av网址| 成人影片麻豆国产影片免费观看| 亚洲精品无码久久久久A片苍井空 亚洲精品无码久久久久YW | 日韩免费在线中文字幕| 国产精品亚洲综合一区| 国产在线观看免费av站| 亚洲一区二区中文| 黄页免费的网站勿入免费直接进入| 国产亚洲中文日本不卡二区| 四虎永久成人免费| 亚洲六月丁香婷婷综合| 中出五十路免费视频| 亚洲国产精品特色大片观看完整版| 三年片在线观看免费大全电影| 亚洲理论片在线中文字幕| 午夜成年女人毛片免费观看| 杨幂最新免费特级毛片| 黄a大片av永久免费| a毛片成人免费全部播放| 337p日本欧洲亚洲大胆艺术| 国产福利免费观看| 免费高清国产视频| 亚洲一卡2卡3卡4卡乱码 在线 | 亚洲阿v天堂在线2017免费| 免费一区二区无码东京热| 亚洲天堂男人影院| 中文字幕亚洲专区| 无码人妻精品中文字幕免费东京热| 亚洲中文字幕不卡无码| 成人福利免费视频| 一级毛片免费不卡|