前面介紹了如何通過fxml文件編排界面布局,可是光有靜態界面根本沒法處理業務,必須另外書寫業務邏輯的代碼,方能響應各按鈕的單擊事件,並將業務結果即使呈現到界面上。顯然,fxml內部寫不了Java代碼,同時入口程序已經把控件都托管給了fxml文件,也無法在Application代碼中干預控件的操作。既然整個界面都托付給了fxml,那么解鈴還須系鈴人,只能且必須由fxml指定后續的邏輯控制器。具體做法是在fxml的根節點中添加屬性“fx:controller”,通過該屬性設置當前界面的控制器路徑。比如之前的登錄布局文件login_with_flow.fxml,它的根節點是流式窗格FlowPane,所以就給FlowPane節點補充“fx:controller”的取值,詳細的標簽例子見下:
<FlowPane fx:controller="com.javafx.fxml.LoginController" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="5" vgap="5">
由以上的FlowPane標簽可知,它指定的控制器路徑為“com.javafx.fxml.LoginController”,這個LoginController類正是login_with_flow.fxml對應的控制器代碼。作為FXML專屬的搭檔,控制器也要符合一定的格式規范,首先它必須實現了接口Initializable,並重寫該接口定義的initialize方法,這個方法顧名思義會在界面初始化之時調用。其次,控制器內部需要聲明FXML文件定義好的控件編號,這樣才能通過控件編號操作每個控件對象。下面便是一個控制器范本的代碼示例:
//界面控制器必須實現自接口Initializable public class LoginController implements Initializable { @FXML private 控件類型 控件編號; // 其中控件類型為JavaFX的控件類名,控件編號取自fxml文件中的fx:id @Override public void initialize(URL location, ResourceBundle resources) { // 界面打開后的初始化操作 // 可在此給各控件設置單擊事件或者選中事件,也可設置控件上的文本字體及其大小 } }
仍以前述的登錄窗口為例,它的布局文件名叫login_with_flow.fxml,同時fxml文件設定了界面對應的控制器叫做LoginController。注意到登錄窗口擁有兩個單選按鈕和一個登錄按鈕,這三個按鈕都應當觸發單擊或者選中事件,於是在控制器的代碼中分別聲明幾個待操作的控件對象,對象名稱與fxml中的fx:id保持一致。然后重寫控制器的initialize方法,在該方法中各自調用三個按鈕的setOnAction方法,用以注冊單擊或選中按鈕后的觸發事件。根據以上說明編寫登錄窗口的控制器代碼示例如下:
//登錄窗口的界面控制器 public class LoginController implements Initializable { @FXML private RadioButton rbPassword; // 密碼登錄對應的單選按鈕 @FXML private RadioButton rbVerifycode; // 驗證碼登錄對應的單選按鈕 @FXML private Label labelUser; // 用戶名標簽 @FXML private TextField fieldUser; // 用戶名輸入框 @FXML private Label labelPassword; // 密碼標簽 @FXML private PasswordField fieldPassword; // 密碼輸入框 @FXML private Button btnLogin; // 登錄按鈕 @FXML private Label labelLoginResult; // 登錄結果標簽 @Override public void initialize(URL location, ResourceBundle resources) { // 界面打開后的初始化操作 rbPassword.setOnAction(e -> { // 選中“密碼登錄”單選按鈕后觸發的事件 labelUser.setText("用戶名:"); labelPassword.setText("密 碼:"); }); rbVerifycode.setOnAction(e -> { // 選中“驗證碼登錄”單選按鈕后觸發的事件 labelUser.setText("手機號:"); labelPassword.setText("驗證碼:"); }); // btnLogin.setOnAction(e -> { // 單擊“登錄”按鈕后觸發的事件 String result = String.format("您輸入的用戶名為%s,密碼為%s", fieldUser.getText(), fieldPassword.getText()); labelLoginResult.setText(result); // 在登錄結果標簽上顯示登錄信息 }); } }
由上面代碼可見,這個控制器的處理邏輯很簡單,選中按鈕后僅僅給文本標簽設置指定文字而已,當然這樣也方便觀察控件的操作結果。
回到登錄窗口的入口代碼LoginMain,運行測試程序彈出如下圖所示的登錄界面。
由圖示可見登錄窗口默認選中“密碼登錄”,接着單擊右邊的“驗證碼登錄”按鈕,發現下方的用戶名標簽變成了“手機號:”,密碼標簽變成了“驗證碼:”,說明“驗證碼登錄”按鈕的選中事件被正常觸發。然后分別在用戶名輸入框與密碼輸入框中填入用戶名和密碼,再單擊下面的登錄按鈕,此時登錄窗口的界面效果如下圖所示。
果不其然,登錄按鈕下方的文本標簽展示了輸入的用戶名和密碼信息,可知登錄按鈕的單擊事件也正確響應了。
更多Java技術文章參見《Java開發筆記(序)章節目錄》