程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用JRuby和Swing進行跨平台開發

使用JRuby和Swing進行跨平台開發

編輯:關於JAVA

使用 Monkeybars JRuby Swing 庫快速開發桌面應用程序

使用 Ruby 除了可以構建 Web 和控制台應用程序外,還可以編寫復雜的 GUI 桌面應用程序,這些桌 面應用程序可以不作修改地在多種平台上運行。得益於 JRuby,Ruby 的傳統 C 實現的健壯替代品,Ruby GUI 工具包可以使用用於 Java 平台的 UI 工具。本文介紹一個用 JRuby 和 Swing 構建應用程序的庫 Monkeybars,並講解一個示例應用程序。

Ruby 目前被作為一種用於構建 Web 應用程序的編程語言而 著稱,主要通過 Ruby on Rails 框架使用。但是,這種語言還可以用於開發圖形化桌面應用程序。在本 文中,您將學習更多關於使用 Ruby 進行桌面應用程序開發的知識,並完成一個詳細的示例,這個示例使 用 Monkeybars — 一個基於 Swing 和 JRuby 的開源庫 — 創建一個 GUI 桌面應用程序。

面向桌面的 Ruby

標准的 Ruby 發行版包括用於 Tk 綁定的代碼,Tk 是一組開源的、跨平 台部件集,用於創建圖形化桌面應用程序。這可以帶來很大的方便。但是,在從源代碼安裝 Ruby 時,應 確認同時還有 Tk 依賴關系,並確保編譯設置包括 Tk。如果在 Windows® 上使用方便的 “一 鍵式(one-click)” 安裝程序包安裝 Ruby,那麼仍然需要采取額外步驟使 Tk 工作,因為它不再 支持自動安裝。

即使為 Ruby 設置了 Tk,它仍然有點沉悶。在某些目標平台上,它們看上去相當 丑陋。而且,創建復雜的接口令人生畏。Tk 最適合用於較小的 GUI 需求。

可用工具包

Tk 的這些弱點促使了其他面向 Ruby 的 GUI 工具包選項的開發(請參閱 參考資料 查看相關鏈接)。有些 值得注意的選擇是:

FxRuby:FxRuby 是用於 Fox 的 Ruby 綁定,這是一個用 C 編寫的 GUI 工 具包。它可用於使用 RubyGems 的安裝。對於 Windows,有一個二進制 gem;用於其他平台的 gem 則需 要編譯本地代碼。

WxRuby: WxRuby 是用於跨平台 wxWidgets C++ GUI 工具包的一個綁定,通過 它可以創建擁有本地外觀的桌面應用程序。它可用於使用 gem 的安裝。

QtRuby:QtRuby 提供對 Qt 工具包(在 KDE 桌面系統中使用的工具包)的 Ruby 綁定。對於 Windows 安裝,有一個 gem,但是 對於其他平台則只有源代碼。

GTK-Ruby:GTK 是在 GNOME 中使用的 UI 工具包。要使之運行,需 要編譯本地代碼。

Shoes:Shoes 是最近出現的一個與 Ruby GUI 部件有關的工具包。與這份列表 中提到的其他工具包不同的是,它是專門為 Ruby 設計的。可以使用特定於平台的安裝程序來安裝它。

Swing:Swing?是的,正是這個與每個 Java 運行時環境捆綁的 GUI 庫。如果您運行 JRuby,那 麼可以使用 Swing。

除了其中一個外,所有這些都是用 C 或 C++ 編寫的 GUI 或部件庫,它們都 有相應的綁定,以允許在其他語言,例如 Ruby、Python 和 Perl 中調用它們。在幾乎所有情況下,您都 要面對多種考慮,例如安裝和發行。

如何選擇 GUI 庫

當然,選擇使用哪個 GUI 工具集取 決於您的特定需要。需要考慮以下內容:

一套豐富的部件或組件

可靠的實現

在多 種平台上的可用性(主要是 Macintosh、Win32、KDE 和 GNOME)

在托管平台上的本地感觀

是否受到積極的維護

易於創建定制的部件

未受限的許可

可接受的成本

可用於加快開發的已有的框架和庫

成熟的 IDE 和窗體布局工具

測試工具和框架

易於打包和部署

如果只需偶爾拋出消息框,或者請求用戶進行某些簡單的輸入,那麼前面 列出的所有工具包都適用。對於簡單的需求,只需重點考慮平台可用性、適合的部件以及適當的成本。如 果打算發布應用程序,那麼需要檢查工具包許可。另外,還必須確保用戶已經有所需的環境,或者很容易 將所有需要的庫和部件放到一個獨立的應用程序或一個安裝包中。

但是,對於復雜的應用程序, 需求就變得嚴格起來。對於任何超越了簡單窗體的應用程序,幾乎肯定需要有一個窗體設計工具。另外還 需要一套豐富的可用部件;不過,可以重用一個已有的數據采集器或文件浏覽器組件,而不必自己編寫它 們。

每個不同的基於 C 的 Ruby GUI 工具包都有其擅長的一面,但是它們當中沒有明顯的勝者。 對於常規的 Ruby 跨平台桌面開發,並沒有顯而易見的選擇。在不同程度上,它們都有安裝、文檔化、設 計工具、打包和部署方面的問題。值得注意的是,逐一對比特性,它們當中沒有哪個能超過非 C 語言編 寫的工具包。

利用 Java 技術

JRuby 是用於 Java 平台的一個 Ruby 實現(請參閱 參考資料)。它使您可 以通過 JVM 執行 Ruby 代碼。在 JRuby 下運行的 Ruby 代碼還可以裝載和使用 Java 庫,包括 Swing。

對於 JRuby + Swing 的一些爭議

從好的方面看,Swing 組件的數量非常多;從壞的方面 看,它們是 Swing 對象;雖然可以將它們裝載到 Ruby 代碼中,但是必須知道它們五花八門的 API 和怪 異的語法。雖然 Swing 有豐富的文檔和示例,但是除非編寫圍繞這些組件的 Ruby 包裝器,否則必須親 自處理一些原始的 Swing 代碼。

第二個常見的反對理由是,Swing 看上去可能不如某些工具包, 例如 Qt 那麼漂亮或自然。但是,這不是一成不變的,Swing 現在的外觀已經相當不錯了。

在 Java 平台與基於 C 的工具之間進行權衡時,必須做出一些選擇,決定什麼才是最重要的。例如,Swing 可以完全免費使用,而 Qt 對於商業和開源應用程序則有不同的成本和限制。另一方面,Qt 組件的感觀 對於您的程序來說可能更好一些。

Java 平台的某些方面使得 JRuby 成為一個好的選擇:

它比較穩定,並且經過良好的測試

它有較強的社區和供應商支持

它有很多良好的文檔

有很好的 IDE 和 UI 布局工具可供選擇

可免費使用(不管是在成本方面還是許可方面)

用戶機器上可能已經安裝了 Java 運行時

如果用(J)Ruby 編寫應用程序,並使用 Swing 實現 UI,則只需確保用戶有最新版本的 Java 運行時,並在打包應用程序時包括 JRuby JAR 文件。由於 已經有了用於 JRuby 應用程序打包的 Ruby 工具,所以這些不成問題。

(J)Ruby + Swing 的開發 人員選項

對於從 Ruby 中使用 Swing,有很多選項:

原始的、手工編寫的對 Swing 對象 的內聯調用:在最簡單的情況下,可以像引用任何其他 Ruby 對象那樣引用 Swing 對象:

panel = Java::javax::swing::JFrame.new("JRuby panel")
panel.show

“Builder” 和領域特定語言(DSL)風格的庫:全部以手工代碼構造面 板和窗體,然後添加組件,這樣可以提高開發速度。有一些庫使 Swing 交互更具 Ruby 風格。例如:

Cheri::Swing 使用 Ruby 塊語法生成 Swing 代碼。

另一個庫 Profligacy 則圍繞原始的 Swing 調用提供了一個 Ruby 包裝器,它可以幫助您用更少的原始 Java 代碼編寫更多的 Swing 代碼。 為了恰當地使用 Swing 組件,仍然需要熟悉 Swing API 文檔。

這些方法都假設面板、窗體和布 局是用手工代碼創建的。雖然用純 Swing 代碼做這些事情已經是一個進步,但是仍然無法處理復雜的用 戶界面。

“我們不關心 Java 類來自何處” 方法:第三種方法假設用於 Swing 對象 的已編譯的 Java 類已經存在,並試圖使用 Ruby 代碼簡化 Swing 對象的創建。

最後是 Monkeybars 庫采用的方法(請參閱 參考資料)。現在已經有很多非常好的、免費的圖形化 Swing UI 布 局編輯器。和之前提到的 GUI 工具包(例如 Fox 和 GTK)的使用一樣,對於不常見的對話框,不需要 UI 編輯器。但是,除此之外,這類工具是不可替代的,對於一個高級的桌面應用程序,無視這些工具而 手工編寫 UI 並無益處。

Monkeybars

Monkeybars 項目源於 David Koontz 在 Happy Camper Studios 中的產品開發,並在此基礎上有所發展,試圖創建可測試、可維護的復雜的 Ruby 桌面 應用程序。它受到了積極的維護,並且可以完全免費使用。

Monkeybars 是一個開源 Ruby 庫,它 使用一種模型、視圖、控制器(MVC)設計模式將已有的 Java Swing 類(即定義 Swing UI 的已編譯 Java 類)與 Ruby 代碼連接起來。MVC 的目的在於將視圖邏輯和 UI 組件與應用程序邏輯相分離。

由於使用 Java 語言和 Swing 庫,Monkeybars 建立在成熟、健壯的技術之上。與目前用於 JRuby 的其他 Swing 庫不同,它非常適合於構造大型的、復雜的、多面板的應用程序。您將看到,創建 Monkeybars 應用程序需要承擔一定的開銷,所以對於簡單的窗體來說它可能不是最好的選擇。但是,對 於有以下需求的 JRuby 桌面應用程序來說,它是一個合理的選擇:

可靠的跨平台部署(確保用戶 安裝了最新的 JVM)

有大量具有任意復雜度的 UI 部件可供選擇

復雜的 UI 窗體和面板構造和交互

為什麼 使用 Swing 而不是 SWT?

Monkeybars 使用 Swing 而不是 Standard Widget Toolkit(SWT), 原因如下:

Swing 是 Java 編程的一部分;使用 Java 編程的用戶也具備 Swing。

Swing 可對組件的行為進行更細粒度的控制。

Swing 組件在外觀方面具有更大的靈活性。

和 Profligacy 一樣,Monkeybars 不隱藏 Swing API。但是,由於它使用編譯過的 UI 類,因此可以充分利 用任何工具或應用程序來生成真正的布局。取決於應用程序的復雜性,幾乎不可避免的是,在編寫 Ruby 代碼的過程中,某些時候需要參考 Swing 組件 API 文檔和代碼示例才能知道怎麼做(但是由於 JRuby 與 Java 庫的良好集成,很容易將那樣的 Swing 代碼包裝在一個 Ruby API 中,以便於重用)。使用 Monkeybars 構建的程序可能有不同程度的復雜性,但是可以遵循一些基本的模式來使代碼易於維護。

實現 MVC 的 Monkeybars 方法

MVC 模式已經有很長的歷史了,並且有很多變體。對於 Monkeybars,基本前提是對於每個 Swing 幀(也就是容納各種組件或 widget 的 UI 對象;在某些情況 下,可能是一個模態面板),有 3 個 Ruby 文件:一個模型、一個視圖和一個控制器。模型類存放實際 的業務邏輯,並管理與應用程序部分對應的數據。視圖或控制器用於作為與模型進行交互的手段,而模型 並不知道它們的存在。將對視圖和控制器的引用放在模型之外,可以使模型更易於開發和測試。

視圖是另一個 Ruby 文件,它引用一個特定的 Java 類,這個 Java 類包含編譯過的 Swing 代碼。視圖 管理 Swing 組件與模型數據的交互。視圖可以直接與模型交互,但是它也使用模型的一個副本,以便將 數據傳遞給控制器。在設計模型類時要謹記這一點,因為它最終要為兩個目的服務。模型的主實例保持長 期狀態,並提供應用程序邏輯;而視圖使用的副本實際上是一個可任意使用的數據訪問對象。模型應該易 於實例化,並為視圖使用的任何數據提供基本的訪問方法。

視圖並不直接與控制器交互。相反, 有一個信號系統來抽象控制器與視圖之間的交互。這種解耦使得視圖和控制器更易於測試。

這段 描述有意簡化和忽略了一些細節。在幕後,視圖與控制器之間有更緊密的交互。基礎設施需要某種手段來 協調行為。Monkeybars 的目的不是束縛您的手腳,而是幫助您創建易於測試和維護的代碼。但是,作為 開發人員,適當的時候可以隨意繞過計劃中的 API。

在控制器類中,可以定義 Swing 事件(例如 單擊按鈕或更改文本字段)的處理程序,並控制模型的狀態。控制器保留對模型主實例的引用。它並不直 接與視圖通信。

當一個控制器需要從視圖獲取數據時,視圖提供模型的一個副本,其中包含當前 的 UI 內容。然後,控制器可以決定用該數據更新模型的主實例,或者根據這些值采取某種操作。控制器 還可以告訴視圖更新自身,並傳回更新後的值。在示例應用程序中,您將看到這一點。

使用 Monkeybars 的一個示例 JRuby Swing 應用程序

為了讓您感覺一下如何使用 Swing 和 Ruby 創建 一個桌面應用程序,我將帶您完成一個簡單的用 Monkeybars 創建的程序(要獲得完整的示例源代碼,請 訪問 下載 中的鏈接)。

准備工作

首先,需要准備好一些東西:

獲得一個 jruby -complete.jar(參考資料 中有下載鏈接)。

安裝 Monkeybars 庫。可以作為 gem 安裝它:

sudo gem install monkeybars

也可以從 gitorious.org 上的庫中獲取 最新的源代碼。

安裝 rawr gem:

sudo gem install rawr

嚴格地講,rawr 對於編寫 Monkeybars 應用程序不是必需的,但是它提供了很多有用的 rake 任務,可 以將 JRuby 應用程序轉換成可執行的 JAR 文件。本文的示例將使用它。

應用程序的基礎

示例應用程序是一個 “flash card” 程序,它讀取一個文本文件,其中定義有很多 “ 卡片”。它循環運行,直到被關閉,它周期性地短暫顯示和隱藏自己。基本上,它是一個學習工具 。對於這個示例,這些卡片是一組德語單詞和短語。該程序還讀取一個配置文件,該文件定義一個卡片定 義文件的位置和一些設置(顯示/隱藏速度,窗口大小)。

這個示例的目標是:

展示 Monkeybars 代碼生成器的使用,它可以自動創建普通的文件

展示 Monkeybars 應用程序的基本結構

演示 Monkeybars MVC 組每個部分的創建

展示 Monkeybars 如何處理應用程序數據到 UI 組件的映射

展示如何將應用程序打包為可執行的 JAR 文件

使用 Monkeybars 應用程序生成器腳本

安裝後,Monkeybars 提供一個命令行腳 本,用於創建一組初始的應用程序文件。要開始一個新的 Monkeybars 項目,可以執行隨 gem 安裝的 monkeybars 腳本。將項目命名為 monkey_see:

$ monkeybars monkey_see

這樣會在 給定的路徑下(或者,如果只提供應用程序的名稱,則在當前目錄下)創建一個新的目錄,並添加用於新 應用程序的核心文件和目錄。

使用 rawr 將代碼自舉到 Java 環境中

rawr 是源於 Monkeybars 的另一個 Ruby 庫。它處理各種打包任務,並提供一個命令行腳本,用於創建一個基本的 Java 類,Monkeybars 應用程序可以使用這個 Java 類來作為 Java 程序執行(而不是通過 JRuby 使應 用程序作為一個 Ruby 程序運行)。

對於這個 Monkeybars 應用程序,為了使用 rawr,可進入項 目目錄,並執行 rawr 腳本:

$ cd money_see; rawr install

使用 Monkeybars rake 任務生成文件

您已經看到了 Monkeybars 如何劃分模型、視圖和控制器。慣例是將這些文件放在 相同的目錄中。Monkeybars 提供了一個 rake 任務,用於生成這些文件。您可以創建其中任何一個文件 或全部 3 個文件(後者更常見):

$ rake generate ALL=src/flash

該命令在 src/ 下創建一個名為 flash 的子目錄,其中有 3 個文件:flash_controller.rb、flash_view.rb 和 flash_model.rb。前兩個文件有從基本 Monkeybars 類繼承而來的骨架類。模型代碼則不是這樣; Monkeybars 並不假定您如何管理應用程序邏輯和數據;那完全由您決定。

創建 UI

對於應 用程序的界面,需要一個 Swing 類,以顯示 flash-card 數據。如何創建這個 Swing 類由您決定。 Monkeybars 中沒有任何東西使它與任何特定的 UI 工具或 Swing 代碼生成器綁定。按照慣例,Swing 文 件與它的相關元組放在同一個目錄中(src/flash/FlashFrame.java)。您需要知道類包,以便將它傳給 視圖類(使用 flash 包,並將類命名為 FlashFrame)。

您的屏幕布局看上去應該如圖 1 所示:

圖 1. 應用程序的屏幕布局

一些關鍵點:應該 使用一個 JTextPane 來顯示 flash-card 的內容,以便使用 HTML 來格式化所呈現的文本。另外,對於 文本面板和按鈕,還應該使用容易理解的名稱。這樣一來,在處理視圖時,就更容易知道一些關於 UI 組 件的信息。這個程序的代碼是用 Ruby 編寫的,所以應使用 Ruby 命名慣例:將文本命名為 pane card_pane,將兩個菜單項命名為 edit_menu_item 和 quit_menu_item。另外再為它們提供快捷鍵。

幀本身的名稱並不重要。視圖類可以直接按名稱引用組件。

定義模型

模型管理指 定 UI 背後的應用程序邏輯和數據。一個 Monkeybars 程序通常對於每個 Java 窗體有一個模型。示例應 用程序只有一個模型,用於處理 flash-card 數據。模型代碼需要能夠從一個已知的位置裝載數據,並提 供一個公共方法用於提供那些數據。

為簡單起見,將數據存儲在應用程序運行時所在子目錄下的 一個文本文件中。這裡不要硬編碼 HTML,而是使用 Textile 標記,並使用 RedCloth Ruby 庫來轉換它 。每個卡片條目由一個分隔字符串分隔開。

使用第三方的庫

Textile 是一個文本標記格式 ,用於使用簡單的純文本慣例定義 HTML。例如,為了表示 <em>italicized</em>,可以編 寫 _italicized_。RedCloth 是一個以 gem 的形式提供的 Ruby 庫,它可以將 Textile 格式的文本轉換 成 HTML。

Rubygems 使得安裝和使用第三方的庫變得非常容易,但是,由於您想將代碼打包到一 個 JAR 中,並且還可能發布它,所以需要確保與應用程序相關的所有代碼都被打包。為此,解壓 RedCloth gem,並將 redcloth.rb 文件復制到項目的 ruby/lib/ 目錄中:

$ cd /tmp; gem unpack RedCloth

這將創建 /tmp/RedCloth-3.0.4 /(除非安裝了不同版本的 gem)。將 /tmp/RedCloth-3.0.4/lib/redcloth.rb 復制到 monkey_see 項目的 lib/ruby/ 目錄。

通常,不屬於應用程序核心部分的任何 Ruby 庫都應該放在 lib/ruby/ 中(這是慣例)。如果使用 gem,那麼需要解壓實際的庫文件,並將它們添加到項目中。在本文的後面,您將看到怎樣告訴程序如何發現這些文件。

關鍵模型方法

load_cards 方法從磁盤讀取文本文件,劃分出每個卡片,並將結果賦給 @cards 實例變量。

select_card 方法隨機選取一張卡片,並將它賦給 @current_card 實例變量。您將使用 attr_accessor 來定義用於讀取和設置這個變量的方法。

無論 UI 中顯示哪張卡片,都可以在那裡編輯它。經過編輯之後,update_current_card 方法獲取 @current_card 的內容,並重新將它插入到 @cards 數組中。save 方法將 @cards 數組寫回到磁盤。

current_card 方法的值就是要呈現的值,為了呈現這個值,需要一個視圖類。

定義視圖類

Monkeybars 視圖類是 Java Swing 類的所有者。如果打開 flash_view.rb,可以看到,它調用了一個類方法 set_java_class。這應該被設置成為這個視圖定義的 Swing 類。在您的代碼中,這是 flash.FlashFrame。

通常,一個 Monkeybars 視圖類需要做 3 件事:

將數據傳入和傳出 Swing 組件

管理各種以視圖為中心的行為(例如大小和位置)

對控制器發出的信號做出響應

映射數據

Monkeybars 提供了一個 map 方法,通過該方法可以定義如何將模型方法連接到 Swing 控件。最簡單的用法是連接一個 UI 組件方法和一個模型方法:

map :view => :card_pane.text, :model => :current_card

該映射使用默認行為,即使之成為一個直接的、雙向的關聯。也就是說,card_pane 組件的 text 方法的結果被傳遞到模型的 current_card= 方法。當根據模型更新視圖時,這個過程又反過來了:

model.current_card 填充 card_pane.text.(注意:JRuby 處理 Ruby/Java 命名轉換,所以實際的 Swing 方法 setText 可以使用 set_text = 來調用。)

這種簡單的映射常常很好用,但是在某些時候,由於數據類型、格式或某個應用程序邏輯的不同,您不希望直接進行數據交換。Monkeybars 允許在數據交換中使用中介。可以為映射傳遞一個 :using 參數(即指向一個數組的一個 hash 鍵),該參數表明當將數據從模型轉移到視圖和從視圖轉移到模型時所使用的替代方式(使用 :using 的另一個原因是處理這樣的情況,即需要用不符合常規的 getProperty 和 setProperty 模式的組件方法或子對象來操縱 Swing 組件的值或狀態)。

對於您的代碼,需要從模型中獲取一個 Textile 格式的字符串,並在將它賦給 card_pane text 屬性之前將它轉換成 HTML。為此,您將創建 to_html 方法。另外,您不想直接從視圖中更新模型的 current_card 值。在視圖中,您將有專門的代碼用於編輯卡片,所以在本應使用 view-to-model 之類的方法名的地方,您將使用 nil。

結果就是這樣的映射:

map :view  => :content_pane.text,
:model => :current_card, :using => [:to_html, nil ]

您還希望 Swing 幀以特定的方式顯示。默認情況下,Swing 幀出現在屏幕的左上角。對於您的應用程序,您希望它顯示在屏幕的右上角。您還將給它一個幻燈片效果,使它不至於突然地出現和消失。

管理 Swing 對象

視圖類有一個專用的實例變量 @main_view_component,它引用相應的 Swing 類。視圖代碼通過這個對象與 Swing 組件交互。例如,為了更改 flash-card 文本面板的內容,可以編寫:

@main_view_component.card_pane.text = "Some new text"

但是,這種代碼實際上正是需要視圖類存在的理由,所以 Monkeybars 讓您不必顯式地使用 @main_view_component,而是直接引用它的組件:

card_pane.text = "Some new text"

基本 Monkeybars::View 類使用 method_missing 來攔截那樣的代碼,看它是不是一個組件引用,如果是,則將請求委托給 @main_view_component。

方法是在 Swing 類上調用的,不過需要顯式的引用:

@main_view_component.width = 500

為了取得精美的幻燈片效果,視圖類有一些用於操縱 Swing 幀的高度和位置的方法,以便圖形化地對它進行縮放,使得在每個呈現周期中,它從屏幕的頂端滑下,然後又縮回。

處理來自控制器的請求

Monkeybars 被設計用來解耦 MVC 元組的關鍵部分。由於視圖有對 Java Swing 對象的直接引用,因此它通常是最難以測試的部分。Monkeybars 的目的是減少視圖與模型和控制器的直接交互。但是,控制器負責處理 UI 事件。不可避免的是,這意味著控制器需要指導視圖做出響應。但是,控制器並不直接與視圖類通信。相反,它使用信號。

稍後您將看到控制器端的情況。在視圖中,您需要使用 define_signal 方法定義信號處理程序。它帶有 2 個參數,一個是信號名稱,另一個是用於處理那個信號的視圖方法:

define_signal :name => :initialize,
:handler => :do_roll_up

處理程序方法必須帶 2 個參數:一個是模型(從控制器傳入),另一個是傳輸對象。傳輸對象是一個短暫的 hash,用於在控制器與視圖之間來回移動數據。視圖中有為 UI 的初始位置、幻燈片出現、幻燈片消失定義的信號,還有 2 個分別為開始和結束卡片編輯而定義的信號。每種信號的處理程序都很短。下面是 do_roll_up method:

def do_roll_up model, transfer
hide
move_to_top_right
roll_up
end

編輯序列是通過菜單事件觸發的。Edit 菜單項控制編輯。在視圖中,編輯序列意味著設置

card_pane.editable = true,然後用原始的 Textile 卡片文本換出用 HTML 呈現的內容。另外還需要更

改組件的內容類型,以便它正確地呈現純文本。

當編輯完成時,則執行相反的過程。面板呈現 HTML,而 editable 則被設置為 false。視圖只負責管理

Swing 組件的狀態;控制器則指示模型執行文本更新和保存。

定義控制器類

嵌套的控制器

Monkeybars 控制器通常是作為單獨的類使用的;通常不需要多個實例。但是,有一個例外值得注意,那就是嵌套控制器的使用,在此情況下,一個幀或面板有多個子組件,它們是同一個類的不同實例,這超出了本文的討論范圍。實際上,您可以將一組復雜的幀、面板和組件劃分到不同的 MVC 元組中。一個例子就是地址簿,一個頂級 Swing 幀呈現多個地址對象,而每個地址對象又是一個 address_entry MVC 集合的實例。

您的 Swing 對象有一些菜單項,但是不必將任何用於這些菜單項的代碼放到視圖類中。那些代碼屬於控制器。控制器處理所有 UI 事件,例如單擊按鈕、選擇菜單以及更改文本字段。Monkeybars 為此作了安排,在默認情況下,來自 Swing 代碼的所有事件都被毫無察覺地處理。對於您關心的那些事件,必須定義事件處理程序。在這個示例應用程序中,需要捕捉的事件是單擊菜單。

事件處理程序的形式如下:

def your_component_name_action_performed
# code
end

(如果想在代碼中使用實際的 Swing 事件,也可以在定義處理程序時以實際的 Swing 事件作為參數。)

要處理 Quit 菜單項,只需退出:

def quit_menu_item_action_performed
java.lang.System.exit(0)
end

Edit 菜單動作則復雜一點:

def edit_menu_item_action_performed
if @editing
@editing = false
signal :end_edit
update_card
else
@editing = true
signal :begin_edit
update_model view_model, :current_card
end
end

以上代碼通過使用信號驅動視圖來處理編輯模式的開關。要注意的關鍵一點是,卡片文本是如何通過使用

控制器的模型實例(通過信號暗中傳遞給視圖)和 view_model 方法提供的視圖的模型副本進行轉移的。

每當控制器需要用戶界面的當前狀態時,它可以使用 view_state 方法來引用視圖的模型副本和當前的傳

輸對象。由於從 view_state 獲取模型副本非常常見,所以 Monkeybars 提供了 view_model 方法。

您的控制器還有一個用於實現初始呈現的方法和一個用於顯示/隱藏顯示序列的方法。這兩個方法都使用

信號將實際的顯示代碼交給視圖處理。

編排應用程序

除了一個或多個 MVC 元組外,Monkeybars 應用程序還使用 2 個關鍵的助手文件來准備和運行代碼。

這 2 個文件都在 src/ 目錄中。manifest.rb 文件設置庫裝載路徑,並允許根據程序是直接從文件系統運行還是從一個 JAR 文件運行來定義包括哪些文件。

之前,您已將 redcloth.rb 添加到 lib/ruby/ 中。為了讓應用程序能找到這個文件,需要將那個目錄添加到裝載路徑中。對於 lib/java/ 目錄也是如此。所以,應確保 manifest.rb 包括以下幾行:

add_to_load_path "../lib/java"
add_to_load_path "../lib/ruby"

main.rb 也是在 src/ 中。這是應用程序的 Ruby 入口點。除了其他事情外,它定義一個全局錯誤處理程序,在此將放置在執行主應用程序邏輯之前要運行的特定於平台的代碼。

示例程序使用一個簡單的循環:

begin
  flash_card = FlashController.instance
  flash_card.init_view :flash_interval_seconds => 8,
                       :show_for_seconds => 20,
                       :window_height => 200,
                       :data_src => 'data/cards.rc'
  while true do
    flash_card.present
  end
rescue => e
  show_error_dialog_and_exit(e)
end

執行代碼

關於生成的 JAR 文件的一些說明

rawr:jar 創建的 JAR 文件並不包含執行程序所需的所有東西。特別是,任何包含程序所需的庫的 JAR(例如 jruby-complete.jar 和 monkeybars-0.6.4.jar)都沒有放在 monkey_see.jar 中。

當 rawr:jar 運行時,它在 package/deploy/ 下創建一組文件。這些是執行應用程序所需的文件,它們必須在一起發布。通過 build_configuration.yaml 文件可以操控將哪些文件放入到 JAR 中,以及將哪些文件和目錄復制到部署目錄中。例如,data/cards.rc 文件可以放到 monkey_see.jar 中,但是由於這個應用程序允許編輯,所以它應該作為一個外部文件,以便寫回更改。

.有了代碼以及合適的數據文件後,就可以運行程序。使用一個 rawr rake 任務創建一個可執行的 JAR 文件。如果在項目的一開始運行了 rawr install,那麼它會在 src/org/rubyforge/rawr/ 下創建一個 Main.java 文件。從 JAR 運行程序需要一個 Main Java 類;rawr 可以生成這個文件,它包含查找和解釋 main.rb 文件的基本代碼(或者,如果沒有找到該文件,它將創建一個這樣的文件,並使用該文件)。

rake rawr:jar 任務編譯該代碼,並將文件打包到一個 JAR 中。build_configuration.yaml 文件用於協調此過程。在創建 JAR 之前,要先編輯這個文件,以反映應用程序的細節。

要啟動程序,首先構建 JAR 文件:

$ rake rawr:jar

然後調用它:

$ java -jar package/deploy/monkey_see.jar

應該可以看到 flash-card 屏幕從右上角滾下,停留一會兒,然後又向上滾回。

當窗口可見時,可以使用菜單項編輯當前顯示的卡片。如果要退出,可以使用 Quit 菜單項(如果添加了快捷鍵 Alt+Q 的話,也可以使用該快捷鍵)。

結束語

作為 Ruby 的傳統 C 實現的健壯的、可用的替代品,JRuby 意味著 Ruby GUI 工具包可以超越其他使用 C 實現的工具包,而使用為 Java 平台提供的 UI 工具。由於 Swing 是 Java 運行時安裝的一個標准部分,Swing 組件為 (J)Ruby 提供了一個成熟的、可立即使用的圖形工具包。使用 Java 平台意味著應用程序很容易在多個平台上構建、打包和發布給用戶。通過使用 Monkeybars 庫,Ruby 開發人員可以更輕松地構建易於測試和維護的復雜的桌面應用程序。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved