GEF入門系列(五、淺談布局).doc_第1頁
GEF入門系列(五、淺談布局).doc_第2頁
GEF入門系列(五、淺談布局).doc_第3頁
GEF入門系列(五、淺談布局).doc_第4頁
GEF入門系列(五、淺談布局).doc_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

GEF入門系列(五、淺談布局)雖然很多GEF應(yīng)用程序里都會用到連接(Connection),但也有一些應(yīng)用是不需要用連接 來表達關(guān)系的,我們目前正在做的這個項目就是這樣一個例子。在這類應(yīng)用中,模型對象間 的關(guān)系主要通過圖形的包含來表達,所以大多是一對多關(guān)系。 圖1 不使用連接的GEF應(yīng)用先簡單描述一下我們這個項目,該項目需要一個圖形化的模型編輯器,主要功能是在一個 具有三行N列的表格中自由增加/刪除節(jié)點,節(jié)點可在不同單元格間拖動,可以合并相鄰節(jié)點 ,表格列可增減、拖動等等。由于SWT/Jface提供的表格很難實現(xiàn)這些功能,所以我們選擇了 使用GEF開發(fā),目前看來效果還是很不錯的(見下圖),這里就簡單介紹一下實現(xiàn)過程中與圖 形和布局有關(guān)的一些問題。在動手之前首先還是要考慮模型的構(gòu)造。由于Draw2D只提供了很有限的Layout,如 ToolbarLayout、FlowLayout和XYLayout,并沒有一個GridLayout,所以不能把整個表格作為 一個EditPart,而應(yīng)該把每一列看作一個EditPart(因為對列的操作比對行的操作多,所以 不把行作為EditPart),這樣才能實現(xiàn)列的拖動。另外,從需求中可以看出,每個節(jié)點都包 含在一個列中,但仔細再研究一下會發(fā)現(xiàn),實際上節(jié)點并非直接包含在列中,而是有一個單 元格對象作為中間的橋梁,即每個列包含固定的三個單元格,每個單元格可以包含任意個節(jié) 點。經(jīng)過以上分析,我們的模型、EditPart和Figure應(yīng)該已經(jīng)初步成形了,見下表:模型EditPartFigure畫布DiagramDiagramPartFreeformLayer列ColumnColumnPartColumnFigure單元格CellCellPartCellFigure節(jié)點NodeNodePartNodeFigure表中從上到下是包含關(guān)系,也就是一對多關(guān)系,下圖簡單顯示了這些關(guān)系:圖2 圖形包含關(guān)系圖讓我們從畫布開始考慮。在畫布上,列顯示為一個縱向(高大于寬)的矩形,每個列有一 個頭(Header)用來顯示列名,所有列在畫布上是橫向排列的。因此,畫布應(yīng)該使用 ToolbarLayout或FlowLayout中的一種。這兩種Layout有很多相似之處,尤其它們都是按指定 的方向排列顯示圖形,不同之處主要在于:當(dāng)圖形太多容納不下的時候,ToolbarLayout會犧 牲一些圖形來保持一行(列),而FlowLayout則允許換行(列)顯示。對于我們的畫布來說,顯然應(yīng)該使用ToolbarLayout作為布局管理器,因為它的子圖形 ColumnFigure是不應(yīng)該出現(xiàn)換行的。以下是定義畫布圖形的代碼:Figure f = new FreeformLayer();ToolbarLayout layout=new ToolbarLayout();layout.setVertical(false);layout.setSpacing(5);layout.setStretchMinorAxis(true);f.setLayoutManager(layout);f.setBorder(new MarginBorder(5);其中setVertical(false)指定橫向排列子圖形,setSpacing(5)指定子圖形之間保留5象素 的距離,setStretchMinorAxis(true) 指定每個子圖形的高度都保持一致。ColumnFigure的情況要稍微復(fù)雜一些,因為它要有一個頭部區(qū)域,而且它的三個子圖形( CellFigure)合在一起要能夠充滿下部區(qū)域,并且適應(yīng)其高度的變化。一開始我用Draw2D提 供的Label來實現(xiàn)列頭,但有一個不足,那就是你無法設(shè)置它的高度,因為Label類覆蓋了 Figure的getPreferedSize()方法,使得它的高度只與里面的文本有關(guān)。解決方法是構(gòu)造一個 HeaderFigure,讓它維護一個Label,設(shè)置列頭高度時實際設(shè)置的是HeaderFigure的高度;或 者直接讓HeaderFiguer繼承Label并重新覆蓋getPreferedSize()也可以。我在項目里使用的 是前者。第二個問題花了我一些時間才搞定,一開始我是在CellPart的refreshVisuals()方法里手 動設(shè)置CellFigure的高度為ColumnFigure下部區(qū)域高度的三分之一,但這樣很勉強,而且還 需要額外考慮spacing帶來的影響。后來通過自定義Layout的方式比較圓滿的解決了這個問題 ,我讓ColumnFigure使用自定義的ColumnLayout,這個Layout繼承自ToolbarLayout,但覆蓋 了layout()方法,內(nèi)容如下:class ColumnLayout extends ToolbarLayout public void layout(IFigure parent) IFigure nameFigure=(IFigure)parent.getChildren().get(0);IFigure childrenFigure=(IFigure)parent.getChildren().get(1);Rectangle clientArea=parent.getClientArea();nameFigure.setBounds(new Rectangle (clientArea.x,clientArea.y,clientArea.width,30);childrenFigure.setBounds(new Rectangle(clientArea.x,nameFigure.getBounds ().height+clientArea.y,clientArea.width,clientArea.height-nameFigure.getBounds ().height);也就是說,在layout里控制列頭和下部的高度分別為30和剩下的高度。但這還沒有完,為 了讓單元格正確的定位在表格列中,我們還要指定列下部圖形(childrenFigure)的布局管 理器,因為實際上單元格都是放在這個圖形里的。前面說過,Draw2D并沒有提供一個像SWT中 FillLayout那樣的布局管理器,所以我們要再自定義另一個layout,我暫時給它起名為 FillLayout(與SWT的FillLayout同名),還是要覆蓋layout方法,如下所示(因為用了 transposer所以horizontal和vertical兩種情況可以統(tǒng)一處理,這個transposer只在 horizontal時才起作用):public void layout(IFigure parent) List children = parent.getChildren();int numChildren = children.size();Rectangle clientArea = transposer.t(parent.getClientArea();int x = clientArea.x;int y = clientArea.y;for (int i = 0; i numChildren; i+) IFigure child = (IFigure) children.get(i);Rectangle newBounds = new Rectangle(x, y, clientArea.width, -1);int divided = (clientArea.height - (numChildren - 1) * spacing) / numChildren;if (i = numChildren - 1)divided = clientArea.height - (divided + spacing) * (numChildren - 1);newBounds.height = divided;child.setBounds(transposer.t(newBounds);y += newBounds.height + spacing;上面這些語句的作用是將父圖形的高(寬)度平均分配給每個子圖形,如果是處于最后的 一位的子圖形,讓它占據(jù)所有剩下的空間(防止除不盡的情況留下空白)。完成了這個 FillLayout,只要讓childrenFigure使用它作為布局管理器即可,下面是ColumnFigure的大 部分代碼,列頭圖形(HeaderFigure)和列下部圖形(ChildrenFigure)作為內(nèi)部類存在:private HeaderFigure name = new HeaderFigure();private ChildrenFigure childrenFigure = new ChildrenFigure();public ColumnFigure() ToolbarLayout layout = new ColumnLayout();layout.setVertical(true);layout.setStretchMinorAxis(true);setLayoutManager(layout);setBorder(new LineBorder();setBackgroundColor(color);setOpaque(true);add(name);add(childrenFigure);setPreferredSize(100, -1);class ChildrenFigure extends Figure public ChildrenFigure() ToolbarLayout layout = new FillLayout();layout.setMinorAlignment(ToolbarLayout.ALIGN_CENTER);layout.setStretchMinorAxis(true);layout.setVertical(true);layout.setSpacing(5);setLayoutManager(layout);class HeaderFigure extends Figure private String text;private Label label;public HeaderFigure() this.label = new Label();this.add(label);setOpaque(true);public String getText() return this.label.getText();public Rectangle getTextBounds() return this.label.getTextBounds();public void setText(String text) this.text = text;this.label.setText(text);this.repaint();public void setBounds(Rectangle rect) super.setBounds(rect);this.label.setBounds(rect);單元格的布局管理器同樣使用FillLayout,因為在需求中,用戶向單元格里添加第一個節(jié) 點時,該節(jié)點要充滿單元格;當(dāng)單元格里有兩個節(jié)點時,每個節(jié)點占二分之一的高度;依次 類推。下面的表格總結(jié)了各個圖形使用的布局管理。由表可見,只有包含子圖形的那些圖形 才需要布局管理器,原因很明顯:布局管理器關(guān)心和管理的是子圖形,請時刻 牢記這一點。布局管理器直接子圖形畫布ToolbarLayout列列ColumnLayout列頭部、列下部-列頭部無無-列下部FillLayout單元格單元格FillLayout節(jié)點節(jié)點無無這里需要特別提醒一點:在一個圖形使用ToolbarLayout或子類作為布局管理器時,圖形 對應(yīng)的EditPart上如果安裝了FlowLayoutEditPolicy或子類,你可能會得到一個 ClassCastException異常。例如例子中的CellFigure,它對應(yīng)的EditPart是CellPart,其上 安裝了CellLayoutEditPolicy是FlowLayoutEditPolicy的一個子類。出現(xiàn)這個異常的原因是 在FlowLayoutEditPolicy的isHorizontal()方法中會將圖形的layout強制轉(zhuǎn)換為FlowLayout ,而我們使用的是ToolbarLayout。我認為這是GEF的一個疏忽,因為作者曾說過FlowLayout 可應(yīng)用于ToolbarLayout。幸好解決方法也不復(fù)雜:在你的那個EditPolicy中覆蓋 isHorizontal()方法,在這個方法里先判斷l(xiāng)ayout是ToolbarLayout還是FlowLayout,再根據(jù) 結(jié)果返回合適的boolean值即可。最后,關(guān)于我們的畫布還有一個問題沒有解決,我們希望表格列增多到一定程度后,畫布 可以向右邊擴展尺寸,前面說過畫布使用的是FreeformLayer作為圖形。為了達到目的,還必 須在editor里設(shè)置rootEditPart為ScalableRootEd

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論