歡迎您光臨本站 註冊首頁

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

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  
使用 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 創建的程序(要獲得完整的示例源代碼,請訪問 下載 中的鏈接)。

準備工作

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

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

  2. 安裝 Monkeybars 庫。可以作為 gem 安裝它:
    sudo gem install monkeybars  

    也可以從 gitorious.org 上的庫中獲取最新的源代碼(參見 參考資料)。

  3. 安裝 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 開發人員可以更輕鬆地構建易於測試和維護的複雜的桌面應用程序。

本文的示例非常簡單,它主要介紹在 JRuby Swing GUI 開發中可以做什麼事情。在 Monkeybars 站點可以找到更多的信息和更複雜的示例。(責任編輯:A6)



[火星人 ] 使用 JRuby 和 Swing 進行跨平台開發已經有749次圍觀

http://coctec.com/docs/linux/show-post-69092.html