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

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

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

    sharky的點(diǎn)滴積累

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      56 隨筆 :: 104 文章 :: 10 評(píng)論 :: 0 Trackbacks

    在目前的GEF版本(3.1M6)里,可用的LayoutManager還不是很多,在新聞組里經(jīng)常會(huì)看到要求增加更多布局的帖子,有人也提供了自己的實(shí)現(xiàn),例如這個(gè)GridLayout,相當(dāng)于SWT中GridLayout的Draw2D實(shí)現(xiàn),等等。雖然可以肯定GEF的未來(lái)版本里會(huì)增加更多的布局供開(kāi)發(fā)者使用(可能需要很長(zhǎng)時(shí)間),然而目前要用GEF實(shí)現(xiàn)表格的操作還沒(méi)有很直接的辦法,這里說(shuō)說(shuō)我的做法,僅供參考。

    實(shí)現(xiàn)表格的方法決定于模型的設(shè)計(jì),初看來(lái)我們似乎應(yīng)該有這些類(lèi):表格(Table)、行(Row)、列(Column)和單元格(Cell),每個(gè)模型對(duì)象對(duì)應(yīng)一個(gè)EditPart,以及一個(gè)Figure,TablePart應(yīng)該包含RowPart和ColumnPart,問(wèn)題是RowFigure和ColumnFigure會(huì)產(chǎn)生交叉,想象一下你的表格該使用什么樣的布局才能容納它們?使用這樣的模型并非不能實(shí)現(xiàn)(例如使用StackLayout),但我認(rèn)為這樣的模型需要做的額外工作會(huì)很多,所以我使用基于列的模型。

    在我的表格模型里,只有三種對(duì)象:Table、Column和Cell,但Column有一個(gè)子類(lèi)HeaderColumn表示第一列,同時(shí)Cell有一個(gè)子類(lèi)HeaderCell表示位于第一列里的單元格,后面這兩個(gè)類(lèi)的作用主要是模擬實(shí)現(xiàn)對(duì)行的操作--把對(duì)行的操作都轉(zhuǎn)換為對(duì)HeaderCell的操作。例如,創(chuàng)建一個(gè)新行轉(zhuǎn)換為在第一列中增加一個(gè)新的單元格,當(dāng)然在這同時(shí)我們要讓程序給其余每一列同樣增加一個(gè)單元格。

    geftable.gif
    圖1 表格編輯器

    現(xiàn)在的問(wèn)題就是怎樣讓用戶(hù)察覺(jué)不到我們是在對(duì)單元格而不是對(duì)行操作。需要修改的地方有這么幾處:一是創(chuàng)建新行或改變行位置時(shí)顯示與行寬一致的插入提示線,二是在用戶(hù)點(diǎn)擊位于第一列中的單元格(HeaderCell)時(shí)顯示為整個(gè)行被選中,三是允許用戶(hù)通過(guò)鼠標(biāo)拖動(dòng)改變行高度,最后是在改變行所在位置或大小的時(shí)候顯示正確的回顯(Feedback)圖形。下面依次介紹它們的實(shí)現(xiàn)方法。

    調(diào)整插入線的寬度

    在我們的調(diào)色板里有一個(gè)Row工具項(xiàng),代表表格中的一個(gè)行,它的作用是創(chuàng)建新的行。注意這個(gè)工具項(xiàng)的名字雖然叫Row,實(shí)際上用它創(chuàng)建的是一個(gè)HeaderCell對(duì)象,創(chuàng)建它的代碼如下:

    tool = new CombinedTemplateCreationEntry("Row", "Create a new Row", HeaderCell.class, new SimpleFactory(HeaderCell.class), CbmPlugin.getImageDescriptor(IConstants.IMG_ROW), null);

    創(chuàng)建新行的方式是從調(diào)色板里拖動(dòng)它到想要的位置。在拖動(dòng)過(guò)程中,隨著鼠標(biāo)所在位置的變化,編輯器應(yīng)該能顯示一條直線,用來(lái)表示如果此時(shí)放開(kāi)鼠標(biāo)新行將插入的位置。由于這個(gè)工具代表的是一個(gè)單元格,所以缺省情況下GEF會(huì)顯示一條與單元格長(zhǎng)度相同的插入線,為了讓用戶(hù)感覺(jué)到是在插入行,我們必須改變插入線的寬度。具體的方法是在HeaderColumnPart的負(fù)責(zé)Layout的那個(gè)EditPolicy(繼承FlowLayoutEditPolicy)中覆蓋showLayoutTargetFeedback()方法,修改后的代碼如下:

    protected void showLayoutTargetFeedback(Request request) {
        super.showLayoutTargetFeedback(request);
        
    // Expand feedback line's width
        Diagram diagram = (Diagram) getHost().getParent().getModel();
        Column column 
    = (Column) getHost().getModel();
        Point p2 
    = getLineFeedback().getPoints().getPoint(1);
        p2.x 
    = p2.x + (diagram.getColumns().size() - 1* (column.getWidth() + IConstants.COLUMN_SPACING);
        getLineFeedback().setPoint(p2, 
    1);
    }

    其中p2代表插入線中右邊的那個(gè)點(diǎn),我們將它的橫坐標(biāo)加上一個(gè)量即可增加這條線的長(zhǎng)度,這個(gè)量和表格當(dāng)前列的數(shù)目有關(guān),和列間距也有關(guān),計(jì)算的方法看上面的代碼很清楚。這樣修改后的效果如下圖所示,拖動(dòng)行到新的位置時(shí)也會(huì)使用同樣的插入線。

    insertline.gif
    圖2 與表格同寬的插入線

    選中整個(gè)行

    缺省情況下,鼠標(biāo)點(diǎn)擊一個(gè)單元格會(huì)在這個(gè)單元格四周產(chǎn)生一個(gè)黑色的邊框,用來(lái)表示被選中的狀態(tài)。為了讓用戶(hù)能選中整個(gè)行,要修改HeaderCell上的EditPolicy。在前面一篇帖子里已經(jīng)專(zhuān)門(mén)講過(guò),單元格作為列的子元素,要修改它的EditPolicy就要在ColumnPart的EditPolicy的createChildEditPolicy()方法里返回自定義的EditPolicy,這里我返回的是自己實(shí)現(xiàn)的DragRowEditPolicy,它繼承自GEF內(nèi)置的ResizableEditPolicy類(lèi),它將被HeaderColumnPart加到子元素HeaderCellPart的EditPolicy列表。現(xiàn)在就來(lái)修改DragRowEditPolicy以實(shí)現(xiàn)整個(gè)行的選中。

    首先要說(shuō)明,在GEF里一個(gè)圖形被選中時(shí)出現(xiàn)的黑邊和控制點(diǎn)稱(chēng)為Handle,其中黑邊稱(chēng)為MoveHandle,用于移動(dòng)圖形;而那些控制點(diǎn)稱(chēng)為ResizeHandle,用于改變圖形的尺寸。要改變黑邊的尺寸(由單元格的寬度擴(kuò)展為整個(gè)表格的寬度),我們得繼承MoveHandle并覆蓋它的getLocator()方法,下面的代碼是我的實(shí)現(xiàn):

    public class RowMoveHandle extends MoveHandle {
        
    public RowMoveHandle(GraphicalEditPart owner, Locator loc) {
            super(owner, loc);
        }

        
    public RowMoveHandle(GraphicalEditPart owner) {
            super(owner);
        }

        
    //計(jì)算得到選中行所占的位置,傳給MoveHandleLocator作為參考
        public Locator getLocator() {
            IFigure refFigure 
    = new Figure();
            Rectangle rect
    =((HeaderCellPart) getOwner()).getRowBound();
            translateToAbsolute(rect);
            refFigure.setBounds(rect);
            
    return new MoveHandleLocator(refFigure);
        }

    }

    在getLocator()方法里,我們調(diào)用了HeaderCellPart的getRowBound()方法用于得到選中行的位置和尺寸,這個(gè)方法的代碼如下(放在HeaderCellPart里是因?yàn)樵贖andle里通過(guò)getOwner()可以很容易得到EditPart對(duì)象),行尺寸的計(jì)算方法與前面插入線的情況類(lèi)似:

    public Rectangle getRowBound(){
        Rectangle rect 
    = getFigure().getBounds().getCopy();
        Diagram diagram 
    = (Diagram) getParent().getParent().getModel();
        Column column 
    = (Column) getParent().getModel();
        rect.setSize(diagram.getColumns().size() 
    * column.getWidth() + (diagram.getColumns().size() - 1* IConstants.COLUMN_SPACING, rect.getSize().height);
        
    return rect;
    }

    有了這個(gè)RowMoveHandle,只要把它代替原來(lái)缺省的MoveHandle加到HeaderColumnCell上即可,具體的方法就是覆蓋DragRowEditPolicy的createSelectionHandles()方法,ResizableEditPolicy對(duì)這個(gè)方法的缺省實(shí)現(xiàn)是加一個(gè)黑框和八個(gè)控制點(diǎn),而我們要改成下面這樣:

    protected List createSelectionHandles() {
        List l 
    = new ArrayList();
        
    //四周的黑色邊框
        l.add(new RowMoveHandle((GraphicalEditPart) getHost()));
        
    //下方的控制點(diǎn)
        l.add(new RowResizeHandle((GraphicalEditPart) getHost(), PositionConstants.SOUTH));
        
    return l;
    }

    代碼里用到的RowResizeHandle類(lèi)是控制點(diǎn)的自定義實(shí)現(xiàn),在下面很快會(huì)講到。現(xiàn)在,用戶(hù)可以看到整個(gè)行被選中的效果了。

    rowselection.gif
    圖3 選中整個(gè)行

    改變行的高度

    改變行高度比較自然的方式是讓用戶(hù)選中行后自由拖動(dòng)下面的邊。前面說(shuō)過(guò),GEF里的ResizeHandle具有調(diào)整圖形尺寸的功能,美中不足的是ResizeHandle表現(xiàn)為黑色(或白色,非主選擇時(shí))的小方塊,而我們希望它是一條線就好了,這樣鼠標(biāo)指針只要放在選中行的下邊上就會(huì)變成改變尺寸的樣子。這就需要我們實(shí)現(xiàn)剛才提到的RowResizeHandle類(lèi)了,它是ResizeHandle的子類(lèi),代碼如下:

    public class RowResizeHandle extends ResizeHandle {
        
    public RowResizeHandle(GraphicalEditPart owner, int direction) {
            super(owner, direction);
            
    //改變控制點(diǎn)的尺寸,使之變成一條線
            setPreferredSize(new Dimension(((HeaderCellPart) owner).getRowBound().width, 2));
        }

        
    public RowResizeHandle(GraphicalEditPart owner, Locator loc, Cursor c) {
            super(owner, loc, c);
        }

        
    //缺省實(shí)現(xiàn)里控制點(diǎn)有描邊,我們不需要,所以覆蓋這個(gè)方法
        public void paintFigure(Graphics g) {
            Rectangle r 
    = getBounds();
            g.setBackgroundColor(getFillColor());
            g.fillRectangle(r.x, r.y, r.width, r.height);
        }

        
    //與前面RowMoveHandle類(lèi)似,但返回RelativeHandleLocator以使線顯示在圖形下方
        public Locator getLocator() {
            IFigure refFigure 
    = new Figure();
            Rectangle rect
    =((HeaderCellPart) getOwner()).getRowBound();
            translateToAbsolute(rect);
            refFigure.setBounds(rect);
            
    return new RelativeHandleLocator(refFigure, PositionConstants.SOUTH);
        }

        
    //不論是否為主選擇,都使用黑色填充
        protected Color getFillColor() {
            
    return ColorConstants.black;
        }

    }

    這樣,我們就把控制點(diǎn)拉成了控制線,因?yàn)樗奈恢门c選擇框(RowMoveHandle)的一部分重合,所以在界面上感覺(jué)不到它的存在,但用戶(hù)可以通過(guò)它控制行的高度,見(jiàn)下圖。

    rowresize.gif
    圖4 改變行高的提示

    正確的回顯圖形

    我們知道,在拖動(dòng)圖形和改變圖形尺寸的時(shí)候,GEF會(huì)顯示一個(gè)"影圖"(Ghost Shape)作為回顯,也就是顯示圖形的新位置和尺寸信息。因?yàn)椴僮餍袝r(shí)目標(biāo)對(duì)象實(shí)際是單元格,所以在缺省情況下回顯也是單元格的樣子(寬度與列寬相同)。為此,在DragRowEditPolicy里要覆蓋getInitialFeedbackBounds()方法,這個(gè)方法返回的Rectangle決定了鼠標(biāo)開(kāi)始拖動(dòng)時(shí)回顯圖形的初始狀態(tài),見(jiàn)以下代碼:

    protected Rectangle getInitialFeedbackBounds() {
        
    return ((HeaderCellPart) getHost()).getRowBound();
    }

    這時(shí)的回顯見(jiàn)下圖,在拖動(dòng)行時(shí)也使用同樣的回顯。

    rowfeedback.gif
    圖5 改變行高時(shí)的回顯

    經(jīng)過(guò)上面的修改,對(duì)HeaderCell的操作在界面上已經(jīng)完全表現(xiàn)為對(duì)表格行的操作了。這些操作的結(jié)果會(huì)轉(zhuǎn)換為一些Command,包括CreateHeaderCellCommand(創(chuàng)建新行,你也可以命名為CreateRowCommand)、MoveHeaderCellCommand(移動(dòng)行)、DeleteHeaderCellCommand(刪除行)和ChangeHeaderCellHeightCommand(改變行高)等,在這些類(lèi)里要對(duì)所有列執(zhí)行同樣的操作(例如改變HeaderCell的高度的同時(shí)改變同一行中其他單元格的高度),這樣在界面上才能保持表格的外觀,詳細(xì)的代碼沒(méi)有必要貼在這里了。

    P.S.曾經(jīng)考慮過(guò)另一種實(shí)現(xiàn)表格的方法,就是模型里只有Table和Cell兩種對(duì)象,然后自己寫(xiě)一個(gè)TableLayout負(fù)責(zé)單元格的布局。同樣是因?yàn)樾薷牡墓ぷ髁肯鄬?duì)比較大而沒(méi)有采用,因?yàn)槟菢拥脑捫泻土卸家褂米远x方式處理,而這篇貼子介紹的方法只關(guān)心行的處理就可以了。當(dāng)然,這里說(shuō)的也不是什么標(biāo)準(zhǔn)實(shí)現(xiàn),不過(guò)效果還是不錯(cuò)的,而且確實(shí)可以實(shí)現(xiàn),如果你有類(lèi)似的需求可以作為參考。

    posted on 2005-05-20 10:14 八進(jìn)制 閱讀(1535) 評(píng)論(12)  編輯 收藏 收藏至365Key 所屬分類(lèi): Eclipse

    評(píng)論

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-05-20 17:09 pwb
    八進(jìn)制你好,我寫(xiě)了個(gè)RCP+GEF的程序,GEF是拷貝的eclipse網(wǎng)站上的ShapesDiagram代碼,我實(shí)現(xiàn)了自己的IEditorInput--ShapesEditorInput。下面是ShapesEditor的SetInput方法:
    protected void setInput(IEditorInput input) {
    super.setInput(input);
    ShapesEditorInput in = (ShapesEditorInput)input;
    diagram = in.getModel();
    }
    和OpenEidtor
    ShapesEditorInput shapesIn = new ShapesEditorInput();
    shapesIn.setModel(new ShapesDiagram());
    try {
    configurer.getWindow().getActivePage().openEditor(shapesIn, ShapesEditor.ID);
    }
    其它我也將ide和ui的相關(guān)依賴(lài)項(xiàng)去掉了,但出現(xiàn)這個(gè)錯(cuò)誤
    java.lang.NoClassDefFoundError: org/eclipse/gef/ui/parts/GraphicalEditorWithFlyoutPalette
    和 Unable to instantiate editor,unable to load class。

    能給點(diǎn)建議么?謝謝了。
      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-05-20 18:03 八進(jìn)制
    找不到GraphicalEditorWithFlyoutPalette類(lèi),應(yīng)該是plugin.xml里對(duì)依賴(lài)的定義缺少了<import plugin="org.eclipse.gef"/>,或者是GEF版本太舊,需要3.0以上。
      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-05-22 18:44 pwb
    謝謝解答,這是將RCP+GEF(ShapesDiagram)結(jié)合的例子的代碼,貼在這里希望和我遇到相同問(wèn)題的兄弟看到,用火狐瀏覽器打開(kāi)https://bugs.eclipse.org/bugs/show_bug.cgi?id=91472

      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-05-24 20:19 freegoldlu
    我現(xiàn)在需要在palette 里面 放置2個(gè) 元素 對(duì)應(yīng)一個(gè)model但是要根據(jù)條件顯示2個(gè)不同的figure
    EClass eClass = null;
    eClass = ACMPackage.eINSTANCE.getApplicationComponent();
    combined = new CombinedTemplateCreationEntry(
    "ApplicationComponent",
    "Create a new ApplicationComponent",
    eClass,
    new EObjectTemplateCreationFactory(eClass),
    ImageDescriptor.createFromURL(BlueprintMMEditPlugin.getPlugin().getBundle().getEntry("icons/full/obj16/ApplicationComponent.gif")),
    ImageDescriptor.createFromURL(BlueprintMMEditPlugin.getPlugin().getBundle().getEntry("icons/full/obj16/ApplicationComponent.gif")));
    entries.add(combined);
    eClass = ACMPackage.eINSTANCE.getApplicationComponent();
    combined = new CombinedTemplateCreationEntry(
    "ApplicationComponentGroup",
    "Create a new ApplicationComponentGroup",
    eClass,
    new EObjectTemplateCreationFactory(eClass),
    ImageDescriptor.createFromURL(BlueprintMMEditPlugin.getPlugin().getBundle().getEntry("icons/full/obj16/ApplicationComponent.gif")),
    ImageDescriptor.createFromURL(BlueprintMMEditPlugin.getPlugin().getBundle().getEntry("icons/full/obj16/ApplicationComponent.gif")));
    entries.add(combined);
    只是顯示的label不同,我想在editpart 或policy中得到不同的label名字 (ApplicationComponent, applicationComponentGroup)我應(yīng)該怎么寫(xiě) ,謝謝高手幫我解答
    今天debug了一天 頭都大了 。。。

      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-05-24 21:06 八進(jìn)制
    我覺(jué)得有兩個(gè)辦法:
    一個(gè)是建兩個(gè)類(lèi)都繼承你現(xiàn)在的這個(gè)ApplicationComponent,對(duì)應(yīng)兩個(gè)editpart,問(wèn)題就簡(jiǎn)單多了;
    另一個(gè)是通過(guò)你的EObjectTemplateCreationFactory把label名字傳給模型,比如給它的構(gòu)造方法增加一個(gè)String類(lèi)型的參數(shù),在getNewObject()方法里把參數(shù)的值賦給模型實(shí)例。
      

    # 感謝 2005-05-25 09:57 freegoldlu
    按照第2種方法 ,解決問(wèn)題 非常感謝 :) 如果在policy 或 editpart中 想獲得當(dāng)前palette 中 被選中項(xiàng)的 label ,就是"ApplicationComponentGroup"

    "ApplicationComponent" 這兩個(gè)字符串 應(yīng)該怎么寫(xiě)?
      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-05-25 13:09 八進(jìn)制
    試試EditPart.getViewer().getEditDomain().getActiveTool()
      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-07-11 17:08 陳哲
    我的0Eclipse里邊的程序的字體全是黑的,不知道再么回事,

    特來(lái)請(qǐng)教高手 希望給于指導(dǎo) 謝謝
      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-07-11 22:08 八進(jìn)制
    不知道你用的是哪個(gè)版本的eclipse,到preferences的General->Appearence->Colors and Fonts里設(shè)置一下看看?
      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-08-01 16:21 Px
    浩哥這篇文章寫(xiě)得好,很透徹
      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-08-17 11:03 新手
    eclipse上的VE palette插件面板老是消失了看不到,在哪里可以再次打開(kāi)顯示它?希望能夠得到樓上大俠們的幫助,謝謝!
      

    # re: [Eclipse]GEF入門(mén)系列(十、表格的一個(gè)實(shí)現(xiàn)) 2005-08-17 12:51 八進(jìn)制
    是否縮成一個(gè)豎條了,如果是按一下豎條上方的黑色三角就可以打開(kāi);另一種情況是在選項(xiàng)里隱藏了,試試window-show view里打開(kāi)palette視圖。我沒(méi)用過(guò)VE,說(shuō)的是一般GEF程序的情況。
      
    posted on 2005-08-26 17:15 sharky的點(diǎn)滴積累 閱讀(414) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 黑人粗长大战亚洲女2021国产精品成人免费视频 | 亚洲av综合av一区| 国产精品免费无遮挡无码永久视频| 亚洲AV色香蕉一区二区| 久久WWW免费人成人片| 国产亚洲精品91| 伊人久久大香线蕉亚洲五月天| 国产免费无码AV片在线观看不卡| 亚洲av无码片在线观看| 免费国产在线观看老王影院| 无码精品一区二区三区免费视频| 色偷偷尼玛图亚洲综合| 亚洲成人激情在线| 亚洲国产精品一区二区久久| 免费真实播放国产乱子伦| 91在线老王精品免费播放| 自拍偷自拍亚洲精品偷一| 亚洲综合自拍成人| 亚洲精品99久久久久中文字幕| 1000部禁片黄的免费看| 成年网在线观看免费观看网址| 亚洲日韩乱码中文无码蜜桃臀| 亚洲最大av无码网址| 在线精品免费视频无码的| 亚洲免费在线视频播放| 九九热久久免费视频| 亚洲一欧洲中文字幕在线| 久久精品国产亚洲AV蜜臀色欲| 亚洲自偷自偷在线成人网站传媒| 亚洲精品亚洲人成在线观看| 日韩a级毛片免费观看| 69堂人成无码免费视频果冻传媒 | 亚洲人成网站在线播放影院在线| 亚洲另类春色校园小说| 在线观看亚洲人成网站| 亚洲avav天堂av在线不卡| 亚洲精品人成电影网| 久久亚洲国产精品成人AV秋霞 | 亚洲欧洲精品无码AV| 亚洲国产成人五月综合网| 浮力影院第一页小视频国产在线观看免费|