與Swing一樣,JavaFX依然提供了三種選擇框,它們是復選框CheckBox、單選按鈕RadioButton、下拉框ComboBox,分別說明如下:
一、復選框CheckBox
復選框允許同時勾選多個,已勾選的時候在方框內部打個勾,未勾選的時候顯示空心方框。查看CheckBox的源碼,發現它與Button控件都派生自抽象類ButtonBase,因而CheckBox擁有和Button同樣的set***/get***方法。不同之處主要有以下兩點:
1、關於勾選狀態的設置與判斷:調用setSelected方法可以設置復選框的勾選狀態,調用isSelected方法可以判斷復選框是否被勾選了。
2、關於勾選監聽器的設置:先調用selectedProperty方法獲得復選框的屬性對象,再調用屬性對象的addListener方法設置該復選框的勾選監聽器。下面是給復選框設置單擊監聽器的代碼例子:
CheckBox ck = new CheckBox("滿意"); // 創建一個復選框 ck.selectedProperty().addListener(new ChangeListener<Boolean>() { // 設置復選框的勾選監聽器 @Override public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) { // 單擊復選框會觸發這里的changed方法 } });
接下來舉個具體的案例,餐廳的點餐系統要在界面上羅列各種菜餚,以便顧客勾選准備下單的菜品。簡單起見先列出三道菜餚,對應三個復選框,編寫完成的界面代碼示例如下:
// 獲取復選框的界面 private void getCheckBox(BorderPane borderPane) { VBox vbox = new VBox(); // 創建一個垂直箱子 HBox hbox = new HBox(); // 創建一個水平箱子 CheckBox ck1 = new CheckBox("麻婆豆腐"); // 創建一個復選框 CheckBox ck3 = new CheckBox("清蒸桂花魚"); // 創建一個復選框 CheckBox ck2 = new CheckBox("香辣小龍蝦"); // 創建一個復選框 hbox.getChildren().addAll(ck1, ck2, ck3); // 把三個復選框一起加到水平箱子上 CheckBox[] boxArray = new CheckBox[]{ck1, ck2, ck3}; // 構建復選框數組 Label label = new Label("這里查看菜單詳情"); // 創建一個標簽 label.setWrapText(true); // 設置標簽文本是否支持自動換行 vbox.getChildren().addAll(hbox, label); // 把水平箱子和標簽一起加到垂直箱子上 ck1.selectedProperty().addListener(new ChangeListener<Boolean>() { // 設置復選框的勾選監聽器 @Override public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) { // 拼接並顯示當前的勾選結果,以及已經勾選的菜餚 label.setText(String.format("您%s了%s。當前已點菜餚包括:%s", (ck1.isSelected() ? "點" : "取消"), ck1.getText(), getCheckedItem(boxArray))); } }); ck2.selectedProperty().addListener(new ChangeListener<Boolean>() { // 設置復選框的勾選監聽器 @Override public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) { // 拼接並顯示當前的勾選結果,以及已經勾選的菜餚 label.setText(String.format("您%s了%s。當前已點菜餚包括:%s", (ck2.isSelected() ? "點" : "取消"), ck2.getText(), getCheckedItem(boxArray))); } }); ck3.selectedProperty().addListener(new ChangeListener<Boolean>() { // 設置復選框的勾選監聽器 @Override public void changed(ObservableValue<? extends Boolean> arg0, Boolean old_value, Boolean new_value) { // 拼接並顯示當前的勾選結果,以及已經勾選的菜餚 label.setText(String.format("您%s了%s。當前已點菜餚包括:%s", (ck3.isSelected() ? "點" : "取消"), ck3.getText(), getCheckedItem(boxArray))); } }); borderPane.setCenter(vbox); // 把垂直箱子放到邊界窗格的中央 }
上面代碼用到了新方法getCheckedItem,該方法用來獲取已經選中的所有菜餚,它的代碼定義如下所示:
// 獲取已經選定的菜單 private String getCheckedItem(CheckBox[] boxArray) { String itemDesc = ""; for (CheckBox box : boxArray) { // 遍歷復選框數組 if (box.isSelected() == true) { // 復選框被選中了 if (itemDesc.length() > 0) { itemDesc = itemDesc + "、"; } itemDesc = itemDesc + box.getText(); // 菜單添加選定的菜餚 } } return itemDesc; }
運行包含以上代碼的點餐程序,彈出的窗口初始界面如下圖所示。
從左往右依次單擊三個復選框,界面上的點餐結果分別如下列三張圖所示。
二、單選按鈕RadioButton
在同一小組內的單選按鈕,最多只能選擇其中一個,它被選中時在圓圈內部顯示一個圓點,未選中時只顯示空心圓圈。RadioButton也由ButtonBase派生而來,因此擁有與Button控件同樣的set***/get***方法。區別之處主要有下列兩點:
1、關於加入到一個單選小組:調用單選按鈕的setToggleGroup方法,即可加入到指定的按鈕小組,該小組的控件類型是ToggleGroup。
2、關於單選按鈕的選擇監聽器:JavaFX把這個監聽器改到小組上面了,先調用ToggleGroup對象的selectedToggleProperty方法獲得單選組的屬性對象,再調用屬性對象的addListener方法設置該小組的單擊監聽器。
仍然以點餐系統為例,這次准備讓顧客享用單點的快餐,小店剛開業暫時只提供三種快餐,對應三個單選按鈕,編寫完成的界面代碼示例如下:
// 獲取單選按鈕的界面 private void getRadioButton(BorderPane borderPane) { VBox vbox = new VBox(); // 創建一個垂直箱子 HBox hbox = new HBox(); // 創建一個水平箱子 RadioButton rb1 = new RadioButton("魚香肉絲飯"); // 創建一個單選按鈕 rb1.setSelected(true); // 設置按鈕是否選中 RadioButton rb2 = new RadioButton("香菇滑雞飯"); // 創建一個單選按鈕 RadioButton rb3 = new RadioButton("黑椒牛排飯"); // 創建一個單選按鈕 hbox.getChildren().addAll(rb1, rb2, rb3); // 把三個單選按鈕一起加到水平箱子上 ToggleGroup group = new ToggleGroup(); // 創建一個按鈕小組 rb1.setToggleGroup(group); // 把單選按鈕1加入到按鈕小組 rb2.setToggleGroup(group); // 把單選按鈕2加入到按鈕小組 rb3.setToggleGroup(group); // 把單選按鈕3加入到按鈕小組 Label label = new Label("這里查看點餐結果"); // 創建一個標簽 label.setWrapText(true); // 設置標簽文本是否支持自動換行 vbox.getChildren().addAll(hbox, label); // 把水平箱子和標簽一起加到垂直箱子上 // 設置單選組合的單擊監聽器 group.selectedToggleProperty().addListener(new ChangeListener<Toggle>() { @Override public void changed(ObservableValue<? extends Toggle> arg0, Toggle old_toggle, Toggle new_toggle) { // 在標簽上顯示當前選中的單選按鈕文本 label.setText("您點了" + ((RadioButton)new_toggle).getText()); } }); borderPane.setCenter(vbox); // 把垂直箱子放到邊界窗格的中央 }
運行包含以上代碼的點餐程序,彈出的窗口初始界面如下圖所示。
從圖示可見當前默認選中了第一個快餐“魚香肉絲飯”,此時先后單擊第二個快餐和第三個快餐,界面上的點餐結果分別如下列兩張圖所示。
三、下拉框ComboBox
如果單選小組里面的選項有很多,全部羅列到窗口上勢必占用大量界面空間,故而采用可伸縮的下拉框較為合適。平時只顯示最近一次選中的文字,需要改變的話再單擊彈出下拉列表,在下拉列表中選完再恢復原狀。看起來JavaFX的下拉框跟Swing的功能差不多,不過JavaFX的ComboBox控件用起來頗為怪異,有下面幾點需要特別注意:
1、關於選中某項以及獲取選中項:得先調用下拉框的getSelectionModel方法獲得模型對象,再調用模型對象的相應方法完成指定功能。例如,調用模型對象的select方法可以選中某項,調用getSelectedIndex方法可以獲得選中項的序號,調用getSelectedItem方法可以獲得選中項的對象。
2、關於設置下拉框的字體:ComboBox控件竟然沒提供setFont方法,只能調用setStyle方法通過css樣式設置文本字體及其大小。
3、關於設置下拉框的選擇監聽器:這個操作更復雜,要先調用下拉框的getSelectionModel方法獲得模型對象,再調用模型對象的selectedItemProperty方法獲得該模型的屬性對象,接着調用屬性對象的addListener方法給下拉框添加選擇監聽器。
繼續以點餐系統為例,原來那家快餐店的生意日趨紅火,快餐種類增加了不少,他們的點餐系統也將單選小組改造成了下拉框。改造完成的界面代碼示例如下:
// 獲取下拉框的界面 private void getComboBox(BorderPane borderPane) { VBox vbox = new VBox(); // 創建一個垂直箱子 // 初始化快餐列表 List<String> snackList = Arrays.asList("魚香肉絲飯", "香菇滑雞飯", "黑椒牛排飯", "梅菜扣肉飯", "糖醋里脊飯", "紅燒排骨飯", "台式鹵肉飯"); // 把清單對象轉換為JavaFX控件能夠識別的數據對象 ObservableList<String> obList = FXCollections.observableArrayList(snackList); ComboBox<String> comboBox = new ComboBox<String>(obList); // 依據指定數據創建下拉框 //comboBox.setItems(obList); // 設置下拉框的數據來源 comboBox.getSelectionModel().select(0); // 設置下拉框默認選中第1項 Font font = Font.font("NSimSun", 16); // 創建一個字體對象 comboBox.setStyle(String.format("-fx-font: %f \"%s\";", font.getSize(), font.getFamily())); // 設置下拉框的字體 comboBox.setEditable(false); // 設置下拉框能否編輯。默認不允許編輯 Label label = new Label("這里查看點餐結果"); // 創建一個標簽 label.setWrapText(true); // 設置標簽文本是否支持自動換行 vbox.getChildren().addAll(comboBox, label); // 把水平箱子和標簽一起加到垂直箱子上 // 設置下拉框的選擇監聽器 comboBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> arg0, String old_str, String new_str) { // getSelectedIndex方法可獲得選中項的序號,getSelectedItem方法可獲得選中項的對象 String desc = String.format("您點了第%d項,快餐名稱是%s", comboBox.getSelectionModel().getSelectedIndex(), comboBox.getSelectionModel().getSelectedItem().toString()); label.setText(desc); // 在標簽上顯示當前選中的文本項 } }); borderPane.setCenter(vbox); // 把垂直箱子放到邊界窗格的中央 }
運行包含以上代碼的點餐程序,彈出的窗口初始界面如下圖所示。
單擊下拉框控件,下方彈出一個包含所有快餐的列表框,具體界面如下圖所示。
單擊下拉列表中的某一項,表示換成指定的快餐,此時下拉列表隱藏,下拉框的文字變成剛點的快餐名稱,點餐結果正如下圖所示。
更多Java技術文章參見《Java開發筆記(序)章節目錄》