熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

輕松實現Java用戶界面編程

2013-11-23 19:19:30  來源: Java核心技術 

  Buoy 是一個構建在 Swing 之上的免費用戶界面(UI)工具包它為 UI 開發人員提供了方便性和簡單性在本文中作者用一個簡單的 fractal 用戶界面程序介紹了 Buoy 可以做什麼為什麼這麼做

  第一次嘗試用 Java 語言構建簡單的用戶界面時我對 Swing 接口的復雜性感到有些驚訝老實說有點想打退堂鼓最近一個朋友向我提到他使用的渲染程序 Art of Illusion(請參閱 參考資料)基於一個不同的工具包Buoy推薦它的原因之一是它的界面更友好當他第一次提到它時我以為他在談 BUI而它與 GUI 這個名字的相似是故意的在這裡 B 代表 better(更好)但是名字 Buoy 並不是縮寫

  Buoy 是免費的實際上它是公共的東西它並沒有在某個開放程度合理的許可下發布實際上它根本不受任何許可控制這意味著在任何用 Java 語言編寫的能夠運行 Buoy 的項目中都可以使用 Buoy而不用考慮許可問題因為提供了完整的源代碼所以這個工具包很容易修改和擴展本文基於 Buoy 發行版要求讀者對 Swing 有基本的了解雖然不了解也能對付過去

  示例程序

  我曾經嘗試用 Swing 構建的第一個應用程序最後以失敗告終為了看出工具包之間的對比情況我決定使用 Buoy 來構建這同一個程序文章中的代碼示例全部來自該程序的 Buoy 版本程序生成了一些分形具體地說是迭代的分形基本思想很簡單在平面上定義一系列的線條區段從() 到()圍繞任意一個單位線條定位繪制這些區段之後繪制同一套變形線條用這個區段作為單位向量做起來比說的更容易就像在圖 中看到的

  圖 分形編輯器中的分形

  這個程序的界面相當簡單它有一些界面小部件有一個畫布在畫布上繪制漂亮的圖片還支持用鼠標操縱圖片實際上必須要做的全部工作就是操縱構成原始曲線的點原始曲線會迭代地繪制出來界面還有一個最小化的菜單;它可以打開和關閉文件關閉窗口或者把當前圖像保存為 PNG 格式的文件雖然簡單但是這個界面簡要地提供了一個 Buoy 小部件的合理示例還有相當數量對事件處理系統的體驗

  程序實際的核心代碼 —— 分形生成器 —— 已經寫好了這把這個示例變成一個很好的測試程序當然在更新它的過程中我也發現並且修補了一些 bug

  發行包中包含示例程序的源代碼還有編譯好的類文件和 Buoy 的 JAR 文件(單擊本文頂部或底部的 Code 圖標下載 factaltar)包中還包含一個叫做 frac 的目錄裡面包含一些示例分形如果使用一台 UNIX 風格的機器在路徑中有 Java 編譯器那麼只要運行 make 就能運行它否則需要設置 classpath 包含當前路徑和 Buoy 的 JAR 文件所在的目錄然後運行 FractalViewer 類在 Windows 系統上正確的命令行應當是 java classpath ;Buoyjar FractalViewer

  sed e s/J/B/g

  在第一次深入研究代碼時也許會形成這樣的印象把 Swing 代碼轉換成 Buoy 代碼簡單得就像把 UI 元素名稱中的字母 J 換成 B 一樣簡單例如 FractalViewer 類不再擴展 JFrame;它現在擴展的是 BFrame主要的小部件名稱也可以照此推測得到Spinner 和 slider 像以前一樣有相同的名字只是換了一個字母 MenuBar(菜單條) 仍然由 Menus(菜單)構成菜單則容納 MenuItems

  有些命名轉換略有不同在 Swing 引用 BorderLayout 的地方Buoy 有 BorderContainer一般來說Buoy 的命名轉換相當統一雖然不總是與 Swing 的命名一樣一個明顯的區別是 Buoy 幾乎組合了容器和布局管理器的概念;每種容器類型都知道自己如何布局這大大簡化了設計例如在分形生成器中使用的 LabelWidget 類是一個 BorderContainer;在 Swing 中這可能是一個帶有 BorderLayout 布局管理器的 JPanel

  但是兩者還是有許多相似之處這對適應新東西有很大幫助更重要的是Buoy 構建在 Swing 之上這意味著一般來說如果需要做的事不能輕松地用 Bouy 完成時可以把 Buoy 對象傳遞給它包裝的 Swing 對象對於這種情況如果想訪問一些沒有 Buoy 對應物的 Swing 對象可以簡單地把它包裝在 AWTWidget 對象中這個對象提供了非常薄的包裝器通過它不僅 Buoy 自己的小部件而且所有的小部件都能訪問 Buoy 的小部件 API例如如果發現確實需要 GridBagLayout可能就需要這樣做

  例如FractalPanel 類是一個 AWTWidget在早期設計中 它是 JPanel 的子類 但實際上我並不需要 JPanel 代碼相反我構建了包裝定制類的類 FractalCanvas 它本身是普通的 Canvas 類的一個子類把它變成一個 AWTWidget就可以在它上面利用 Buoy 高效的事件處理機制

  事件處理代碼非常簡單在按下鼠標按鈕時通過 addEventLink() 的魔力Buoy 發送一個新的 MousePressedEvent 事件到 mousePressed() 函數我忽略了按下哪個按鈕這個問題只考慮按住 shift 單擊或普通單擊普通單擊選擇最靠近的點而按住 shift 單擊則重新把顯示居中然後如果鼠標移動那麼每次 Buoy 注意到移動時都會開始發送 MouseDraggedEvent 事件在處理這些事件時FractalPanel 會生成自己的事件

  近觀 PointChangedEvent

  為了讓一些討論更加具體請來看 PointChangedEvent這是一個試驗性的類如果不喜歡它那也只能怪老天了這個類的想法是讓一個類來表示狀態點中的變化編輯器跟蹤當前點 —— 也就是編輯器小部件目前正在編輯的點可以用這些小部件或在分形面板中單擊選擇新的點選擇的是最靠近的點

  我得出這樣一個結論在代碼中大概有三類涉及到點的事件需要從一個類發送到另一個類

  一個是改變某個點的特征 POINT 事件類型如果由編輯器發送就是告訴分形改變原型線條上的點並要求重畫線條如果由分形發送則是告訴編輯器剛剛選中的點的特性

  下一個是選擇某個點可以按索引或位置進行選擇所以如果只提供了索引或位置那麼構造函數會認為意圖是填充其他值有一點特殊的地方點索引 用來表示沒有選中的點所以必須用 表示編輯器正在尋找指定位置的點這可能不漂亮但是有效

  有點意思的是 Fractal 類響應 SELECT 事件的方式如果成功地選擇了一個點就會發回一個新的 POINT 類型的 PointChangedEvent 事件如清單 所示

  清單 用事件回答事件

  case PointChangedEventSELECT:

  if (egetIndex() >= )

  selectPoint(egetIndex());

  else

  selectPoint(egetPoint());

  // just in case they dont know

  event(new FractalChangedEvent(FractalChangedEventSIZE size));

  if (selectedPoint >= && selectedPoint < size)

  event(new PointChangedEvent(selectedPoint points[selectedPoint]));

  else

  event(new PointChangedEvent(selectedPoint null));

  event(new FractalChangedEvent(FractalChangedEventREDRAW));

  break;

  最後移動點是一個特殊情況如果不需要改變點的其他屬性(例如顏色)那麼所要處理的就是位置這就是 MOVE 事件類型在效果上它與 POINT 事件類型效果很像但它不需要事件生成器(通常是 FractalPanel 類)去關心那些它根本不知道的屬性

  INSERT 和 DELETE 事件類型只有部分相關可能應當屬於 FractalChangedEvent 事件

  事件處理

  正如已經開始看到的事件處理是 Buoy 與 Swing 最明顯的不同之處事件處理提供了大量靈活性Buoy 本身的事件集相當豐富且允許您挑選自己感興趣的事件從任何小部件向其他對象發送事件例如如果想在 Swing 中捕獲鼠標事件捕獲事件的類需要實現 MouseListener 接口這個接口有 個函數需要實現即使它們就是擺設也必須實現而且必須使用接口提供的函數名稱更糟的是函數必須是偵聽器接口的公共部分;要麼把這作為公共接口的一部分公開要麼創建一個什麼都不做只是包裝事件偵聽器代碼的內部類

  在 Buoy 中每個小部件都是 EventSource 這意味著可以從每個小部件偵聽事件什麼類型的事件呢?任何類型都可以關鍵的函數是 addEventLink()這允許您指定類偵聽器以及可選的方法每當 EventSource 分派這個類或它的子類的事件時偵聽器都會接收到事件要麼是通過一個叫做 processEvent()的方法要麼是通過在開始調用 addEventLink() 時提供的方法名稱提供的函數不能接受參數也不能接受與指定事件類型兼容的類的對象;父類和接口可以

  這是一個方便的設置可以把不同的事件路由到不同的函數或相同的函數例如MousePressedEvent 和 MouseReleasedEvent 會被分別處理在示例程序中鼠標的按下釋放和拖動分別有不同的線程如清單 所示注意這遠遠超過 Swing 的 MouseListener 所能做的如果用 Swing 編程的話就需要實現 MouseListener 和 MouseMotionListener 這兩個接口

  清單 只挑感興趣的事件

  thisaddEventLink(MousePressedEventclass this mousePressed);

  thisaddEventLink(MouseRele


From:http://tw.wingwit.com/Article/program/Java/hx/201311/26664.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.