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

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

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

    月蝕傳說

    浮躁讓人失去理智
    posts - 25, comments - 101, trackbacks - 0, articles - 0
      BlogJava :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理

    能夠拖動的矩形

    Posted on 2006-10-09 18:59 Dart 閱讀(1694) 評論(6)  編輯  收藏 所屬分類: GEF

    這章我將說一下如何去實(shí)現(xiàn)一個數(shù)據(jù)表在編輯器上顯示,并且能夠進(jìn)行位置和尺寸的改變。我們將涉及到的內(nèi)容有:Figure,EditPolicy,Command。示例代碼下載

    1.在Editor上實(shí)現(xiàn)一個簡單的數(shù)據(jù)表

    上一章中,我們實(shí)現(xiàn)了一個空的Editor,畫布上什么都沒有,今天我會讓它顯示點(diǎn)東西。
    我們已經(jīng)說過了,Editor要顯示一個圖形,是根據(jù)我們給Viewer設(shè)置的模型,找到對應(yīng)的EditPart,然后調(diào)用EditPart的createFigure得到圖形,最后繪制在Editor上,大致如下:

    http://album.sina.com.cn/pic/5414465b02000419



    我們需要做的事情就讓我們的TableEditPart復(fù)寫基類的createFigure方法,然后返回一個Figure圖形,最后再在代碼中更改我們最初設(shè)置的模型內(nèi)容。

    創(chuàng)建TableFigure

    一般來說,當(dāng)我們需要生成一個Figure圖形的時候,最好的辦法就是從Figure類繼承一個新的類出來,然后復(fù)寫Figure的paintFigure方法,繪制出我們想要的圖案。見下代碼:

    public ? class ?TableFigure?extends?Figure?{

    ????
    protected ? void ?paintFigure(Graphics?graphics)?{
    ????????super.paintFigure(graphics);
    ????????
    // ?得到Figure的Bounds
    ????????Rectangle?bounds? = ?getBounds();
    ????????
    // ?在它周圍繪制一個矩形,寬度和高度稍微小一點(diǎn),以便能全部顯示
    ????????graphics.drawRectangle(bounds.x,bounds.y,bounds.width? - ? 1 ?,?bounds.height? - ? 1 );
    ????}
    }


    TableFigure 顯示的是一個矩形圖形。getBounds方法是得到的是Figure的范圍對象,這個對象是一個Recangle類型,包括有圖形的坐標(biāo)(Point),以及尺寸(Dimension),而這個范圍對象并不是我們?nèi)ブ付ǖ模歉鶕?jù)TableFigure的父Figure來給它設(shè)定的。這里需要說一下,在GEF中,EditPart在繪制Figure的時候,步驟是先繪制好自己的Figure,然后查看自己的子EditPart,獲得他們的Figure,確定他們的大小位置(根據(jù)默認(rèn)或者是本身Figure的布局管理器來得到)繪制在自身Figure之上,也就是說,這是一個遞歸的過程。

    修改TableEditPart代碼

    我們已經(jīng)生成了一個TableFigure類,現(xiàn)在我們需要讓TableEditPart的createFigure方法返回這個類的一個實(shí)例。

    public ? class ?TableEditPart?extends?DBEditPartBase?{

    ????
    protected ?IFigure?createFigure()?{
    ????????
    // ?返回Table的Figure
    ???????? return ? new ?TableFigure();
    ????}
    }


    重新設(shè)置模型

    我們創(chuàng)建Editor的時候,在初始化Viewer的方法中,生成了一個Schema模型給它,現(xiàn)在我們需要把我們的Table模型添加上去,也就是說,讓新的Table模型作為Schema的子對象添加進(jìn)去

    protected ? void ?initializeGraphicalViewer()?{
    ????????
    // ?硬編碼生成一個數(shù)據(jù)庫模型
    ????????
    // ?這個數(shù)據(jù)庫中有一個表
    ????????Schema?schema? = ? new ?Schema();
    ????????Table?table?
    = ? new ?Table();
    ????????
    ????????schema.addChild(table);
    ????????
    this .getGraphicalViewer().setContents(schema);
    ????}


    可以看得出來,我們其實(shí)只是修改了我們的模型,但是圖形顯示是和EditPart相關(guān)的,SchemaEditPart是如何得知它會擁有一個子EditPart —— TableEditPart的呢?仔細(xì)看下DBBaseEditPart就可以很清楚了。
    由于我們復(fù)寫了EditPart的getModelChildren,返回的是DBBaseEditPart對應(yīng)模型的子模型,所以EditPart就可以通過這些子模型來得到子編輯單元(Chilren EditPart)

    ???? protected ?List?getModelChildren()?{

    ????????
    if (getModel()?instanceof?DBBase){
    ????????????
    return ?((DBBase)getModel()).getChildren();
    ????????}
    ????????
    return ?super.getModelChildren();
    ????}


    最后讓我們運(yùn)行一下,得到了一個繪制有矩形的Editor:

    http://album.sina.com.cn/pic/5414465b0200041a



    2.初步討論EditPolicy

    在剛才我們實(shí)現(xiàn)的編輯其中,已經(jīng)將Table模型的圖形顯示了出來,但是僅僅只是有一個矩形畫在畫布上,當(dāng)我們點(diǎn)擊它的時候沒有任何反應(yīng),好像完全只是一張靜態(tài)的圖片,我們要的效果的并不是這個,而是需要一個能夠?qū)ζ洳僮鞯膱D形。

    第一章里我簡單地提到了在GEF中事件處理的過程,看看前面的文章可以知道,我們想要能夠?qū)ξ覀冿@示的TableFigure圖形進(jìn)行編輯,需要的是一個能夠處理相關(guān)Request的EditPolicy。

    EditPolicy的類型有很多,大致分為圖形相關(guān)和圖形無關(guān)兩大類,我在這個例子中使用到了這幾個圖形相關(guān)的EditPolicy:LayoutEditPolicy ,NonResizeableEditPolicy。

    LayoutEditPolicy 一般是作為父EditPart所具有的EditPolicy,就是說,如果我們的Figure需要對它的子EditPart進(jìn)行一些圖形方面管理的話,使用這個EditPolicy比較合適。它能夠處理一些容器類EditPart的應(yīng)該具備的操作:增加一個EditPart,刪除一個EditPart,移動子EditPart對應(yīng)圖形等。

    并且它還能夠?yàn)樗淖覧ditPart設(shè)置對應(yīng)的EditPolicy,這樣一來就統(tǒng)一了子EditPart的一些行為。一會我講具體說一下這個問題。

    NonResizeableEditPolicy,顧名思義,它是一個不處理尺寸變化的EditPolicy,但是它能夠處理EditPart對應(yīng)Figure位置變化,由于我們的數(shù)據(jù)表的大小需要根據(jù)它所擁有列來決定,外界不應(yīng)該對它的尺寸進(jìn)行修改,所以我在這里選用了它。

    怎么使用EditPolicy呢?EditPolicy是被"安裝"到EditPart上的,在EditPart中,有一個接口方法:createEditPolicies,我們要在這里面進(jìn)行安裝。安裝EditPolicy使用installEditPolicy方法。

    回過頭再看看我們所要用的這兩個EditPolicy,他們兩個都應(yīng)該安裝到哪個EditPart上呢。很顯然,LayoutEditPolicy應(yīng)該安裝到父EditPart,也就是SchemaEditPart,這樣一來,SchemaEditPart就能對TableEditPart進(jìn)行管理了; NonResizeableEditPolicy就應(yīng)該屬于TableEditPart,我們需要用它來改變TableEditPart對應(yīng)Figure 的位置。

    當(dāng)然,LayoutEditPolicy和NonResizeableEditPolicy不能實(shí)例化后直接安裝到 EditPart上,因?yàn)槲覀冞€需要復(fù)寫他們的一些方法,稍后我們會提到。我們先創(chuàng)建兩個類,分別繼承LayoutEditPolicy, NonResizeableEditPolicy:

    public ? class ?SchemaLayoutEditPolicy?extends?LayoutEditPolicy?{

    ????
    protected ?EditPolicy?createChildEditPolicy(EditPart?child)?{
    ????????????? ?
    return ? null ;
    ????}
    ????
    protected ?Command?getCreateCommand(CreateRequest?request)?{
    ????????????? ?
    return ? null ;
    ????}

    ????
    protected ?Command?getDeleteDependantCommand(Request?request)?{
    ????????????????
    return ? null ;
    ????}

    ???
    protected ?Command?getMoveChildrenCommand(Request?request)?{
    ????????????? ?
    return ? null ;
    ????}

    }

    ?

    public ? class ?TableNonResizableEditPolicy?extends?NonResizableEditPolicy?{

    }


    很明顯,這輛個類只是繼承了基類,并沒有復(fù)寫或?qū)崿F(xiàn)基類的方法。
    姑且這樣,我們先把SchemaLayoutEditPolicy安裝到SchemaEditPart上:

    ???? protected ? void ?createEditPolicies()?{
    ????????
    this .installEditPolicy(EditPolicy.LAYOUT_ROLE, new ?SchemaLayoutEditPolicy());
    ????}

    installEditPolicy 的第一個參數(shù)其實(shí)并沒有什么用,這個參數(shù)是一個String類型,隨便寫個字符串也不會影響到我們EditPolicy的安裝以及它的工作的(也有人說,如果第一個參數(shù)重復(fù)的話,EditPolicy會被覆蓋掉。我沒有研究過,各位朋友可以試一下)。

    好了,SchemaEditPart所需要的EditPolicy已經(jīng)搞定,剩下TableEditPart了。大家可能會認(rèn)為,安裝它的EditPolicy也和 SchemaEditPart一樣,復(fù)寫createEditPolicies方法,然后installEditPolicy即可。是的,這樣沒有問題,但是由于我們的SchemaLayoutEditPolicy中有這么一個接口方法:createChildEditPolicy,這就是我在前面所說的,為了統(tǒng)一管理,給子EditPart安裝所對應(yīng)的EditPolicy。雖然這樣做和直接安裝的效果差不多(應(yīng)該是一樣,但是也有可能有一些差別),但是我認(rèn)為還是把子EditPolicy的安裝交給父EditPolicy吧:

    ???? protected ?EditPolicy?createChildEditPolicy(EditPart?child)?{
    ????????
    if (child?instanceof?TableEditPart)? return ? new ?TableNonResizableEditPolicy();
    ????????
    return ? new ?NonResizableEditPolicy();
    ????}

    好了,讓我們運(yùn)行一下。呵呵,是不是可以點(diǎn)擊我們的“數(shù)據(jù)表”了。但是這樣還是不能移動我們的數(shù)據(jù)表。

    3. 修改我們的類 ;Command 的使用


    第一章我已經(jīng)講過了,我們的模型有時需要添加一些和模型本身無關(guān)但和圖形有關(guān)的屬性。因?yàn)檫@樣一來我們就能夠記錄我們的圖形發(fā)生的位置變化,再通過模型的改變?nèi)ネㄖ狤ditPart刷新我們的圖形。
    我們先為Table增加一個屬性:location

    ???? protected ?Point?location? = ? new ?Point( 0 , 0 );
    ????
    /* *
    ?????*?@return?返回?location.
    ?????
    */
    ????
    public ?Point?getLocation()?{
    ????????
    return ?location;
    ????}
    ????
    /* *
    ?????*?@param?location?設(shè)置?location?
    ?????
    */
    ????
    public ? void ?setLocation(Point?location)?{
    ????????Point?old?
    = ? this .location;
    ????????
    this .location? = ?location;
    ????}


    這個屬性代表了圖形目前所在的位置坐標(biāo)。

    有朋友要問:這里只是有了屬性,那當(dāng)屬性改變的時候怎么去通知呢?我記得我也在第一章講了,一般的做法是為我們的模型增加一個屬性更改的事件發(fā)生源:PropertyChangeSupport

    我們把事件發(fā)生源寫到基類DBBase中,并增加幾個方法去發(fā)送事件以及添加刪除監(jiān)聽器:

    ???? public ? static ?final?String?PRO_FIGURE? = ? " __figure__property " ;
    ????
    ????
    private ?PropertyChangeSupport?support? = ? new ?PropertyChangeSupport( this );

    ?
    public ? void ?addPropertyChangeListener(PropertyChangeListener?l){
    ????????support.addPropertyChangeListener(l);
    ????}
    ????
    ????
    public ? void ?removePropertyChangeListener(PropertyChangeListener?l){
    ????????support.removePropertyChangeListener(l);
    ????}
    ????
    ????
    public ? void ?fireFigurePropertyChange(Object?old,Object?now){
    ????????support.firePropertyChange(PRO_FIGURE,old,now);
    ????}


    好了,我們的事件源做好了,下面該想想讓誰去監(jiān)聽了。

    毫無疑問,我們的監(jiān)聽器應(yīng)該是DBBaseEditPart,因?yàn)樗庞心芰θニ⑿翭igure,所以我們需要更改DBBasEditPart代碼,如下:

    public ? class ?DBEditPartBase?extends?AbstractGraphicalEditPart?implements?PropertyChangeListener{
    ????
    public ? void ?activate()?{
    ????????
    if (getModel()? != ? null ? && ?getModel()?instanceof?DBBase){
    ????????????((DBBase)getModel()).addPropertyChangeListener(
    this );
    ????????}
    ????????super.activate();
    ????}
    ?????
    public ? void ?deactivate()?{
    ????????
    if (getModel()? != ? null ? && ?getModel()?instanceof?DBBase){
    ????????????((DBBase)getModel()).removePropertyChangeListener(
    this );
    ????????}
    ????????super.deactivate();
    ????}
    ????
    public ? void ?propertyChange(PropertyChangeEvent?evt)?{
    ???????String?pName?
    = ?evt.getPropertyName();
    ???????
    if (pName.equals(DBBase.PRO_FIGURE)){
    ???????????
    this .refreshVisuals();
    ???????}
    ????}
    }


    大家注意下propertyChange方法,當(dāng)我們在獲得事件類型為PRO_FIGURE后,就會直接去調(diào)用refreshVisuals去刷新我們的Figure。
    但是refreshVisuals其實(shí)是空方法,它什么都沒有做!

    所以我們必須在TableEditPart中要復(fù)寫它:

    ??? protected ? void ?refreshVisuals()?{
    ????????super.refreshVisuals();
    ????????
    // ?得到當(dāng)前Figure的位置和大小
    ????????Rectangle?rect? = ? this .getFigure().getBounds();
    ????????
    ????????
    // ?獲得更改后的位置
    ????????Point?p? = ?((Table)?getModel()).getLocation();
    ????????
    ????????
    // ?我們只更改Table的位置
    ????????((GraphicalEditPart)? this .getParent()).setLayoutConstraint( this ,? this
    ????????????????.getFigure(),
    new ?Rectangle(p,?rect.getSize()));
    ????}

    最后一句代碼是什么含義呢?這是讓TableEditPart去找到它的父EditPart,也就是SchemaEditPart,再讓它去“約束” TableEditPart圖形的位置和大小,當(dāng)然了,我們這里沒有改變大小,只是通過Table模型的Location屬性去更改它的位置而已。當(dāng)調(diào)用了setLayoutConstraint方法后,我們的圖形就會自動進(jìn)行重繪。

    接下來,讓Table模型中更改location屬性時將更改事件發(fā)送出來,以便EditPart能夠截獲并處理:

    ????public?void?setLocation(Point?location)?{
    ????????Point?old?
    =?this.location;
    ????????
    this.location?=?location;
    ????????
    this.fireFigurePropertyChange(old,this.location);
    ????}


    我們已經(jīng)做了很多調(diào)整,改了不少代碼了,這會運(yùn)行看看吧!

    對不起,我們的TableFigure還是不會移動!
    這是由于我們忘記了在TableNonResizeableEditPolicy中做文章。

    剛才已經(jīng)說過了,TableNonResizeableEditPolicy能夠處理對圖形移動的,但是它只是通知我們圖形移動了,要找我們索取一個 Command去執(zhí)行這種變化。所以我們還需要寫一個Command類,讓這個Command去執(zhí)行對模型位置的更改(關(guān)于Command的介紹請回過頭看第一章):

    public?class?TableMoveCommand?extends?Command?{

    ????
    private?ChangeBoundsRequest?request;
    ????
    ????
    private?Table?model;

    ????
    public?void?execute()?{
    ??????Point?old?
    =?getModel().getLocation();
    ??????
    int?x?=?request.getMoveDelta().x;
    ??????
    int?y?=?request.getMoveDelta().y;
    ??????
    ??????getModel().setLocation(
    new?Point(old.x+x,old.y+y));
    ????}
    }

    然后我們在TableNonResizeableEditPolicy中復(fù)寫getMoveCommand方法:

    ?protected?Command?getMoveCommand(ChangeBoundsRequest?request)?{

    ????????TableMoveCommand?command?
    =?new?TableMoveCommand();
    ????????command.setModel((Table)getHost().getModel());
    ????????command.setRequest(request);
    ????????
    return?command;
    ????}

    好了!這會再運(yùn)行看看,是不是能移動了?

    4.結(jié)束語

    我們今天把上次例子代碼進(jìn)行了一些修改,得到了一個能夠隨意改變位置的矩形,其中主要簡單地講述了一些EditPolicy如何使用。
    本人文筆比較爛,說事情總說不清,如果有不清楚的地方請留言,我會進(jìn)行修改,盡量讓大家都能看懂。
    以后的章節(jié),我們會繼續(xù)討論EditPolicy以及Figure布局等問題。

    評論

    # re: 能夠拖動的矩形  回復(fù)  更多評論   

    2007-01-12 16:57 by 過客[匿名]
    編輯器中,通過實(shí)現(xiàn)PaletteRoot工具,可以將自己定義的模型拖入到編輯器中,該模型以圖形化的形式在編輯器中顯示

    那如何將視圖中TreeViewer的節(jié)點(diǎn)(每個節(jié)點(diǎn)都有相應(yīng)的模型對應(yīng))拖入到編輯器中呢?

    # re: 能夠拖動的矩形  回復(fù)  更多評論   

    2007-03-13 15:58 by 匿名
    根本允許起來后看不到矩形啊

    # re: 能夠拖動的矩形  回復(fù)  更多評論   

    2007-03-13 17:16 by Dart
    先確認(rèn),你用的Eclipse和GEF是什么版本的,這篇文章寫得比較老了,Eclipse版本應(yīng)該是3.0.1,GEF版本也應(yīng)該是對應(yīng)當(dāng)時Eclipse版本的.
    代碼應(yīng)該不會有問題,因?yàn)樵谶@篇文章還沒有丟失之前很多人都已經(jīng)用過了

    # re: 能夠拖動的矩形  回復(fù)  更多評論   

    2007-03-13 17:33 by 匿名
    在3.2上面能運(yùn)行起來嘛,第五篇的代碼可以運(yùn)行,但第二章的運(yùn)行了沒有看不到矩形.

    # re: 能夠拖動的矩形  回復(fù)  更多評論   

    2007-03-14 13:01 by Dart
    3.2可能跑不起來,我沒試過

    # re: 能夠拖動的矩形  回復(fù)  更多評論   

    2007-04-06 12:54 by xx
    看不到矩形是因?yàn)闆]有設(shè)置矩形大小,默認(rèn)的大小為0,0,看不到而已
    主站蜘蛛池模板: 久久丫精品国产亚洲av| 久久免费视频99| 亚洲伦理中文字幕| 久久国产精品亚洲一区二区| 亚洲精品高清在线| 成年人免费视频观看| 51视频精品全部免费最新| 中文字幕视频免费在线观看| 最新亚洲人成无码网站| 国产亚洲福利在线视频| 亚洲美女自拍视频| 亚洲伦理一区二区| 好看的电影网站亚洲一区| 久久精品亚洲男人的天堂| 免费日本黄色网址| 国产高清免费在线| 我要看WWW免费看插插视频| 91精品成人免费国产片| 久久aⅴ免费观看| 免费日本一区二区| 青青操免费在线观看| 本免费AV无码专区一区| 精品一区二区三区高清免费观看 | 中国xxxxx高清免费看视频| 久久精品成人免费看| a级毛片在线免费| 搡女人免费免费视频观看| 丝袜捆绑调教视频免费区| 91国内免费在线视频| 最近国语视频在线观看免费播放| 国产区在线免费观看| 一区二区在线视频免费观看| 亚洲国产免费综合| 中文字幕成人免费高清在线视频| fc2免费人成在线视频| 成年女人A毛片免费视频| 一个人免费视频观看在线www| 久久免费视频网站| 4444www免费看| 久久久久久久久免费看无码| 成人影片麻豆国产影片免费观看|