轉載:http://blog.sina.com.cn/s/blog_4b6047bc01000bex.html
解決復雜問題常用的一個方法是分析綜合法,或曰分而治之,即將復雜的問題分解成簡單的子問題。解決了每個子問題后,再將它們集成起來。若每個子問題還是太復雜,則可重復此過程直至簡單到容易解決為止。如果問題本身比較復雜,但又不容易繼續分下去,則可試着將問題模型進行簡化,在此基礎上開發出原型后,再陸續添加其其他功能,逐步豐富直至接近問題的原始規模。
Swing界面設計工具是比較復雜的軟件系統。在開發之前,我們應該先將它進行分析簡化。根據以前的經驗,這類工具的功能模塊大體上分為三個部分:
1.界面設計組件,以所見即所得的可視化方式顯示當前正在設計的界面,功能包括組件的選取和編輯兩大部分,其中選取根據類型可分為單選、多選、區域選擇、組件拖放、大小調整等等,組件的編輯包括組件的添加、刪除、復制、剪切、粘帖、對齊、布局管理等等。除這些功能外,界面設計組件還應向屬性編輯頁、組件選擇面板、組件選擇工具欄等系統其他部分提供事件和動作接口。
2.界面設計輔助工具,如屬性、事件、布局的查看和編輯工具屬性頁,設計組件樹的瀏覽、導航和選擇,組件選擇工具欄,以及界面設計工具的編輯操作所對應的工具欄。
3.元數據及代碼解析和生成工具。此部分雖不可見,但卻是界面設計工具的難點和核心。它往往是評價一個界面設計工具優劣的重要標准。
本人打算采取迭代模式開發這個系統,先依序開發各個子模塊,然后最后將他們組合起來。每個階段都會涉及設計->編碼->重構三個元素,程序在不斷演化中前進。
首先考慮界面設計組件的開發。如前文所述,其功能可分為組件選擇和編輯兩方面。組件選擇模塊的特點是在運行時可以共享一套狀態數據,比如當前選擇的組件,當前拖拽的組件,當前鼠標的位置,當前選擇矩形的邊界等等。
實現的思想和技術其實前文都已提到。首先要實現其可視化設計界面的組件。首先可假設當前正在設計的界面組件樹已經在內存構建出來了,其根就是一個Component,在渲染時只要將界面設計的paint方法中,調用根組件的渲染方法paint就能渲染出來。其方法大致如下(在其UI類中):
public void paint(Graphics g, JComponent c) { if (component != null) { //如果當前被設計的組件不為空,則畫出該組件來 paintDesignedComponent(g); } if ((selected_components != null) &&!selected_components.isEmpty()) { //如果當前選中的組件不為空,則畫出他們的resizing邊框來 paintResizing(g); } if (selection_bounds != null) { //如果當前正在選擇組件,畫出選擇框來 g.setColor(SELECTION_COLOR); g.drawRect(selection_bounds.x + LEFT_PAD, selection_bounds.y + TOP_PAD, selection_bounds.width, selection_bounds.height); } } private void paintResizing(Graphics g, JComponent c) { //當前這些選中的組件是否是可以resize的 //帶有布局管理器的容器組件內的組件不應該能resizeable //另外如果所選擇的組件跨了幾個容器,它們也不應該能resizeable boolean resizable = isSelectedResizable(); for (Component comp : selected_components) { Rectangle bounds = getRelativeBounds(comp); g.setColor(SELECTION_COLOR); int x = bounds.x + LEFT_PAD; int y = bounds.y + TOP_PAD; int w = bounds.width; int h = bounds.height; //畫出被選擇組件的高亮邊框 g.drawRect(x, y, w, h); if (resizable) { //如果是resizable,要畫出其拖拽點矩形 drawResizingThumbs(g, x, y, w, h); } } } private void paintDesignedComponent(Graphics g, JComponent c) { //這兒和以前講過的一樣,再使用Renderer技術時,要保證渲染組件是非緩沖的 ArrayList dbcomponents = new ArrayList(); disableBuffer(component, dbcomponents); int width = component.getWidth(); int height = component.getHeight(); //創建相對根組件的剪切窗口圖形對象 Graphics clipg = g.create(LEFT_PAD, TOP_PAD, width, height); //使用跟組件渲染 component.paint(clipg); clipg.dispose(); int x = LEFT_PAD - BORDER_THICK; int y = TOP_PAD - BORDER_THICK; int w = width + 2 * BORDER_THICK; int h = height + 2 * BORDER_THICK; //畫出外邊框來 areaBorder.paintBorder(component, g, x, y, w, h); resetBuffer(dbcomponents); } |
時間不多了,今天先寫到這兒吧。明天再詳細講述如何給界面設計工具加上選擇、鍵盤、編輯等功能。這兒有初步的代碼下載。已經能進行組件選擇、拖放、添加、刪除、復制、粘貼等簡單的編輯動作了。下面是個截圖:
更新:
這兩天做了進一步重構,添加了一些新的功能和注釋。現在的設計界面工具可以進行布局管理,添加了添加提示、添加、刪除、復制、剪切、粘帖、對齊等功能,把組件選擇工具條做了修改,可以添加容器類等等。下面是幾個截圖:




