Hello JavaFX! Part 3
開發Java桌面應用程式,繪圖和動畫效果好像都跟它沒有關係,開發人員的重點通常會在應用程式後端的技術,畫面只不過是讓使用者輸入一些資料後按個按鈕,讓應用程式後端的元件正確而且有效率的儲存或查詢資料。如果大家對桌面應用程式的想法都是這樣的話,那繪圖和動畫效果還真的是浪費時間而且完全沒必要的東西。 不過現在的使用者好像不會這麼想了,他們要求的應用程式功能,當然一個都不能少,執行的效率也要好,正確性更是必要的。除了這些,他們還會提出更過份的要求,就是希望畫面可以好看一些,操作應用程式的時候,如果可以有一些特殊效果,就更好了。 在應用程式執行刪除資料的時候,讓這個資料在畫面上飛到垃圾桶…這個想法可能會讓很多人覺得非常詭異。就算不覺得應該在應用程式中加入這些垃圾效果,一些像是相簿或音樂播放程式,尤其是遊戲,繪圖與動畫效果就一定要了。開發人員想要設計這類應用程式,通常不會想到Java技術,這也是應該的,它真的不太合適。 現在已經包含在Java SE中的JavaFX 2,應該可以改變大家對Java桌面應用程式的想法,開發人員可以用它建立功能強大的商業應用程式,它在2D與3D繪圖和動畫效果支援,不論是實作的方式或執行的效率,都讓人非常滿意,在認識JavaFX的最後一個部份,就來看看它在繪圖和動畫效的基本作法。在瞭解JavaFX應用程式的基本設計以後,最後再說明如何將應用程式發佈給使用者。 My Circles 這個JavaFX應用程式會帶著你認識基本的繪圖與動畫效果,最後完成的應用程式在執行後會像這樣: NetBeans中建立一個JavaFX應用程式,名稱可以取為「MyCircles」,把主程式「MyCircles.java」的「start」方法改成下面的樣子: Group root = new Group(); Scene scene = new Scene(root, 600, 480, Color.BLACK); primaryStage.setScene(scene); Rectangle colors = new Rectangle(scene.getWidth(), scene.getHeight(), null); root.getChildren().add(colors); primaryStage.show(); 執行這個程式以後,會出現一個600X480的視窗,視窗裡面雖然放了一個矩形的Retangle物件,不過現在的畫面會是一片漆黑。JavaFx內建許多繪圖效果的API,在繪製圖形的時候可以指定它們基本的顏色和繪圖效果。在建立Retangle物件之前先建立好一個線性漸層效果的LinearGradient物件,再把它指定給Retangle建構子的最後一個參數: LinearGradient linearGradient = new LinearGradient( 0f, 1f, 1f, 0f, true, CycleMethod.NO_CYCLE, new Stop[]{ new Stop(0, Color.web("#f8bd55")), new Stop(0.14, Color.web("#c0fe56")), new Stop(0.28, Color.web("#5dfbc1")), new Stop(0.43, Color.web("#64c2f8")), new Stop(0.57, Color.web("#be4af7")), new Stop(0.71, Color.web("#ed5fc2")), new Stop(0.85, Color.web("#ef504c")), new Stop(1, Color.web("#f2660f")),}); Rectangle colors = new Rectangle(scene.getWidth(), scene.getHeight(), linearGradient); 再執行應用程式,就可以在視窗中看到線性漸層效果。不過現在加入視窗中的矩形有一個很大的問題,雖然在建立的時候,指定它的大小為視窗的寬與高,如果使用者調整視窗大小的話,就會變成這樣了: 如果希望視窗中的矩形,可以隨著使用調整視窗的大小自動設定的話,一般的作法都會是使用視窗事件來控制。不過JavaFX技術中有一個很重要而且很方便的作法,採用Peoperty和Binding的設定,讓矩形的寬與高自動連結到視窗的寬與高,這樣就方便多了。在建立好Rectangle物件後,加入連結寬與高的程式碼: colors.widthProperty().bind(scene.widthProperty()); colors.heightProperty().bind(scene.heightProperty()); 執行應用程式並調整視窗的大小,矩形已經可以跟著視窗自動調整寬與高了。 Circles 接下來在畫面中加入一些圓環的圖形,而且一次要加入很多個。在JavaFX需要把多個圖形組合起來管理,可以使用「Group」物件,建立好群組務件後,加入30個使用「Circle」類別繪製的圓形。需要設定圖形模糊的效果也很容易在「javafx.scene.effect」套件下有許多用來設定圖形效果的API,這裡使用的是「BoxBlur」它會讓圖形的邊緣產生模糊的效果。在「primaryStage.show();」敘述前加入下面的程式: Group circles = new Group(); for (int i = 0; i < 30; i++) { Circle circle = new Circle(50, Color.web("white", 0.05)); circle.setStrokeType(StrokeType.OUTSIDE); circle.setStroke(Color.web("white", 0.16)); circle.setStrokeWidth(16); circles.getChildren().add(circle); } circles.setEffect(new BoxBlur(10, 10, 3)); root.getChildren().add(circles); 執行程式以後,在視窗的左上角會出現一個四分之一的白色圓環,目前沒有設定這些圓環的位置,所以它們全部都重疊在一起。畫面會像這樣: 這個範例主要的元件都已經加入了,所以可以看看現在視窗中的元件架構: Blend Mode 目前顯示在視窗中的樣子,跟一開始讓你看到的結果還是很不一樣,還差一個混合模式的繪圖效果。加入視窗中的矩形使用線性漸層的繪圖效果,希望可以把它隱藏起來,把它當成底層的顏色,只有在圓環出現的地方,才會顯示線性漸層的顏色。要完成這樣的需求,可以把這兩個群組結合成一個群組,並且把矩形的結合效果設定為圖層。原來的作法是分別加入矩形和圓環群組到畫面中,所以要先找到這兩行敘述並刪除它們: root.getChildren().add(colors); root.getChildren().add(circles); 接下來在「primaryStage.show();」敘述前加入下面的程式: // 把圓環群組跟一個黑色的矩形包裝為一個群組 Group circlesGroup = new Group( new Rectangle(scene.getWidth(), scene.getHeight(), Color.BLACK), circles); // 再把上面的群組跟原來使用線性漸層效果的矩形包裝為一個群組 Group blendModeGroup = new Group(circlesGroup, colors); // 設定使用線性漸層效果的矩形為圖層混合模式 colors.setBlendMode(BlendMode.OVERLAY); root.getChildren().add(blendModeGroup); 執行程式,比較處理前跟處理後的樣子: Time Line 最後要讓這些圓環可以在畫面上動起來,你一定想到執行緒了。執行緒是Java技術中大家最喜歡挑戰的主題了,它很簡單,只有Runnable和Thread兩個;也非常的麻煩,因為真的用了它們以後,一些很奇怪的事情都會出現了。JavaFX API對開發人員還是不錯的,簡化執行緒的作法對動畫效果的製作會有很大的幫助。TimeLine是JavaFX用來代替執行緒的其中一個API,它是一個應用程式中獨立執行的工作。建立好需要的TimeLine物件,為它加入需要的KeyFrame,每一個KeyFrame都可以指定一個執行動畫效果的工作,最後再播放它就可以了。 先看看使用TimeLine讓一個圓環動起來的作法,在「primaryStage.show();」敘述前加入下面的程式: Timeline timeline = new Timeline(); Node circle = circles.getChildren().get(0); timeline.getKeyFrames().addAll( new KeyFrame(new Duration(5000), new KeyValue(circle.translateXProperty(), 600), new KeyValue(circle.translateYProperty(), 0)), new KeyFrame(new Duration(10000), new KeyValue(circle.translateXProperty(), 0), new KeyValue(circle.translateYProperty(), 480) ) ); timeline.play(); 這段程式碼加入兩個KeyFrame,讓第一個圓環在畫面上移動,執行後的結果會像這樣: 瞭解這段程式碼的效果以後,把它們移除掉。接下來讓所有的圓環使用亂數的設定,讓它們在畫面中一起移動。在「primaryStage.show();」敘述前加入下面的程式: Timeline timeline = new Timeline(); for (Node circle : circles.getChildren()) { timeline.getKeyFrames().addAll( new KeyFrame(Duration.ZERO, new KeyValue(circle.translateXProperty(), Math.random() * 600), new KeyValue(circle.translateYProperty(), Math.random() * 480)), new KeyFrame(new Duration(20000), new KeyValue(circle.translateXProperty(), Math.random() * 600), new KeyValue(circle.translateYProperty(), Math.random() * 480) ) ); } timeline.play(); 發佈JavaFX應用程式 想要把寫好的JavaFX應用程式發佈給使用者,目前在NetBeans開發工具中是比較方便的。在NetBeans中建置好一個JavaFX專案後,在「Files」標籤下專案的「dist」目錄中,就包裝好一個可以單獨執行的JAR檔;另外也有一個JNLP檔案,它是一個在網路環境中執行的設定檔,可以讓JavaFX應用程式在Java Web Start或瀏覽器中執行。還有一個HTML檔案,用來啟動Java Web Start和在瀏覽器中執行JavaFx應用程式的樣版,你可以參考它使用在自己的網頁中。 在NetBeans開發環境中,如果沒有特別設定的話,執行JavaFX應用程式都是獨立應用程式的方式。你可以在專案目錄上按滑鼠右鍵,選擇「Properties」,選擇「Run」目錄,在這個設定視窗中,你可以選擇執行JavaFX應用程式的方式。如果選擇在瀏覽器或Java Web Start中執行,也可以設定應用程式的寬度與高度。設定完成候,最好在專案目錄上按滑鼠右鍵後選擇「Clear and Build」,就可以使用新的設定執行JavaFX應用程式了。 資料來源與參考資訊 |
牧野洛
05/11
請問 在"這段程式碼加入兩個KeyFrame,讓第一個圓環在畫面上移動,執行後的結果會像這樣:"之後是不是忘記附圖了?