前言
如今比較流行的桌面gui框架有WPF、WinForm、Qt、javafx等。其中WPF和WinForm目前還只能在運行Winsows上。Qt(widget)是一個很強大的跨平臺C++框架(不只是UI),但用C++寫界面實在有點蛋疼,且編譯出來的體積很大。
JavaFX是基於JAVA的開源桌面框架,筆者曾學習過Qt,打算嘗試使用Java寫桌面應用,現在網上關於JavaFX的教程不時很多,因此在這裏記錄一下學習過程。
安裝和配置
JavaFX11的環境不包括在JDK中,因此要在配置好JDK11的基礎上單獨配置,具體方法可以參考JavaFX官網。
窗口構成
新建工程,在Main.java
中輸入下列代碼:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
VBox layout = new VBox();
Label label = new Label("Hello world");
layout.getChildren().add(label);
Scene scene = new Scene(layout, 300, 300);
primaryStage.setTitle("Hello World");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
JavaFX中的Stage
可以看作是窗口,Scene
是窗口中的內容,調用Stage
的setScene
函數來設置窗口內容,窗口可以在運行時切換顯示的Scene
,實現Tab
頁面的效果。
VBox
是JavaFX中的一種佈局,其中的元素縱向排列,向VBox
中添加元素需要調用vbox.getChildren().add(control)
,如上所示。
構造Scene
時傳入頂層的佈局(類似Qt中QMainWindow
的CentralWidget
)及大小。最後調用show
函數將窗口顯示出來。
按鈕控件
控件(Control)是GUI框架中最重要的部分,也是用戶與程序進行交互的媒介。
在JavaFX中使用控件需要導入包,例如
import javafx.scene.control.Label;
import javafx.scene.control.*;
框架中不同控件的使用方法大同小異,這裏用最常用的按鈕作爲示例。
在窗口中添加按鈕
構造一個Button
對象並添加到VBox
中:
Button button = new Button("Click me");
VBox layout = new VBox();
layout.getChildren().add(button);
Scene scene = new Scene(layout, 300, 300);
primaryStage.setScene(scene);
爲按鈕添加事件
使用EventHandler
接口
創建Handler
類實現EventHandler
接口
class Handler implements EventHandler<ActionEvent> {
@Override
public void handle(ActionEvent actionEvent) {
if(actionEvent.getSource() instanceof Button)
((Button) actionEvent.getSource()).setText("Click me again");
}
}
爲按鈕註冊點擊方法
button.setOnAction(new Handler());
Button
還有setOnMouseClicked
,setOnTouchPressed
等方法,這些是專門爲處理鼠標事件及觸摸事件,setOnAction
函數用來處理按鈕觸發事件(不管按鈕被哪種方式觸發,具體參考文檔)。
由代碼可以得出,setOnAction
函數接收一個EventHandler
接口,接口的handle
方法用來處理事件。
使用匿名內部類
與上一方法同理,我們可以使用匿名內部類創建接口
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
if(actionEvent.getSource() instanceof Button)
((Button) actionEvent.getSource()).setText("Click me again");
}
});
使用Lambda
表達式
Java
中的一些接口可以由lambda
表達式代替,因此可以在setOnAction
中傳入lambda
表達式:
button.setOnAction(actionEvent -> {
if(actionEvent.getSource() instanceof Button){
((Button) actionEvent.getSource()).setText("Click me again");
}
});
這樣就可以在實現簡單的事件處理器時不必再特意實現接口。
其他控件
使用其他控件的方法也都類似按鈕,使用時可以查詢文檔,或者根據IDE的代碼提示獲知函數簽名及使用方法。
多窗口
在一個桌面程序中往往有多個窗口,下面介紹添加窗口的方法。
創建窗口
添加MsgBox
類
public class MsgBox {
public static void show(String title) {
Stage window = new Stage();
window.setTitle(title);
Button trueButton = new Button("True");
Button falseButton = new Button("False");
HBox hBox = new HBox(10); //10爲元素間空隙
hBox.getChildren().addAll(trueButton, falseButton);
Scene scene = new Scene(hBox, 100, 100);
window.setScene(scene);
window.show();
}
}
與主窗口創建過程相同,新建stage
、Scene
、佈局及控件,最後使用Stage
的show
方法顯示出來。
調用MsgBox
類的show
方法即可顯示窗口,函數的參數爲窗口的標題。
設置主窗口中的按鈕事件,點擊按鈕後會顯示一個MsgBox
窗口。
button.setOnAction(actionEvent -> MsgBox.show("SubWindow"));
返回子窗口的值
有時我們需要得到用戶在子窗口中的操作,例如在本文的例子中,獲知用戶點了哪一個按鈕。
接下來實現這樣的功能——點擊True按鈕就在控制檯打印true
,否則打印'false'。
更改MsgBox
中的代碼
public static boolean show(String title) {
Stage window = new Stage();
window.setTitle(title);
Button trueButton = new Button("True");
Button falseButton = new Button("False");
trueButton.setOnAction(actionEvent -> {
answer = true;
window.close();
});
falseButton.setOnAction(actionEvent -> {
answer = false;
window.close();
});
HBox hBox = new HBox(10);
hBox.getChildren().addAll(trueButton, falseButton);
Scene scene = new Scene(hBox, 100, 100);
window.setScene(scene);
window.showAndWait();
return answer;
}
show
函數返回一個boolean
類型的值,這個值是由點擊的按鈕決定的,按鈕點擊後會關閉窗口,返回布爾值。
設置主窗口中按鈕點擊事件
button.setOnAction(actionEvent ->
{
var result = MsgBox.show("SubWindow");
System.out.println(result);
});
showAndWait
函數
這個函數會阻塞當前事件,直到窗口被關閉後纔會返回,並執行接下類的語句。在上例中,我們顯示窗口並等待,直到點擊按鈕使窗口被關閉,才執行後面的return answer
語句。
可以嘗試改爲調用show
方法,觀察返回的結果。
鏈接
- 推薦一個很好的JavaFX教程視頻:https://youtu.be/FLkOX4Eez6o
- 一個適合初學者的Qt教程:https://www.devbean.net/2012/...