Java開發筆記(一百四十)JavaFX的選擇框


與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開發筆記(序)章節目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM