在 使用 clojurescript 和 electron 來打造桌面程式 一文中我們說到了如何使用 electron 搭配 clojurescript 達到在 Node.js 平台使用 HTML 5 來打造桌面程式的方法, 這一次則是來談談如何使用 Clojure 搭配 JavaFX WebView 辦到類似的事情。
JavaFX 是目前 Java 發展的重點項目,自 Java 8 後已經整合進 JRE 裡面,在其中最吸引 我的就是 WebView 組件了,該組件實際上就是一個 WebKit 瀏覽器,既然 Java 8 已經塞 入了 Webkit 支援,也就是說我們可以用寫網頁的方式來建立我們的圖形介面,網頁的運作 流程交給 clojurescript,而大量運算則是由 clojure 來搞定。
本篇文章將談論如何在 Clojure 下用 JavaFX WebView 作為圖形介面,內容則採用 HTML 來進行顯示,為了讓文章更簡單些,這邊只講述如何使用 WebView 的部分。
先來看看 JAVA 要怎樣寫
在剛開始學習 Clojure/Clojurescript 時,常常會需要參考 JAVA/Javascript 了解原本的 程式怎樣運行,接著再將其改寫、修化成更適合 lisp 開發者的函式,也因此學習 Clojure (Clojurescript) 的時候,能看懂 Java (javascript) 是最好的,也易於讓自己學習更愉快。
如果我們要用 JavaFX 寫個簡單一點的瀏覽器要怎樣作呢? 本文使用的原始程式碼如下:
package myapp; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; public class MyApp extends Application { @Override public void start(Stage stage) throws Exception { StackPane root = new StackPane(); WebView view = new WebView(); WebEngine engine = view.getEngine(); engine.load("http://coldnew.github.io"); root.getChildren().add(view); Scene scene = new Scene(root, 800, 600); stage.setScene(scene); stage.show(); } public static void main(String[] args) { Application.launch(args); } }
建立我們的專案
本篇文章還是依照以往的規則,使用預設的 lein 樣板,因此我們這樣建立名為 myapp 的專案:
coldnew@Rosia ~ $ lein new myapp
專案建立完成後,我們要稍微修改一下 project.clj ,加上 :main
讓我們可以使用
lein run
直接執行主程式,同時要記得加入 :aot :all
這一行來啟用 AOT (Ahead of
Time) 編譯。
(defproject myapp "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.7.0"]] :aot :all :main myapp.core)
編輯 core.clj
接著編輯 src/myapp/core.clj
,將原本的內容清除,我們將仿照 Java 的版本一一加上我們的程式
首先是載入我們所需要的套件,在 Clojure 中要載入 Java 的函式庫都需要使用 import
來進行載入,這邊基本上就是你在 Java 裡面會用到哪些模組,在 Clojure 中就用相對應的方式將其載入。
(ns myapp.core (:import [javafx.application Application] [javafx.scene Scene] [javafx.stage Stage] [javafx.scene.layout StackPane] [javafx.scene.web WebView]))
載入完模組後,為了讓 Clojure 可以轉換成 jar 檔,我們要透過 gen-class 來將 myapp.core 這個 class 產生出來,除此之外,透過 gen-class 我們也以告知我們要 擴充的 java class 是哪一個。
(gen-class :name myapp.core :extends javafx.application.Application)
接下來讓我們來定義我們的 main 方法
(defn -main [& args] (Application/launch myapp.core args))
最後就是最主要的部分了, start 是 JavaFX 程式的進入點,和程式的 main 很相 像。 Stage 是應用程式最頂端的容器,會經由 start 傳送過來。 Scene 則是畫面 的內容,我們將 StackPane 置放於我們的 Scene 中,並將 WebView 包入到 StackPane 裡面 (一層包一層的感覺)
(defn -start [this ^Stage stage] (let [root (StackPane.) view (WebView.)] (.load (.getEngine view) "http://coldnew.github.io") (.add (.getChildren root) view) (doto stage (.setScene (Scene. root 800 600)) (.show))))
在這範例中,我們是直接讓 WebView 去載入 http://coldnew.github.io ,也因此當你使
用 lein
去執行這隻程式的時候,你就會看到有一個視窗跑出來,並且載入了我們目標的
網頁。
執行我們的程式
由於我們一開始就在 project.clj
裡面加上了 :aot all
的設定,因此我們可以直接
使用 lein run
來執行並測試這隻程式。
coldnew@Rosia ~/myapp $ lein run
完整程式碼
由於這篇文章的程式很單純,因此我就不提供 git repo 讓各位測試,本文完整的程式碼如 下:
(ns myapp.core (:import [javafx.application Application] [javafx.scene Scene] [javafx.stage Stage] [javafx.scene.layout StackPane] [javafx.scene.web WebView])) (gen-class :name myapp.core :extends javafx.application.Application) (defn -start [this ^Stage stage] (let [root (StackPane.) view (WebView.)] (.load (.getEngine view) "http://coldnew.github.io") (.add (.getChildren root) view) (doto stage (.setScene (Scene. root 800 600)) (.show)))) (defn -main [& args] (Application/launch myapp.core args))