Java開發筆記(一百四十一)JavaFX的列表與表格


下拉框只有在單擊時才會彈出所有選項的下拉列表,這固然節省了有限的界面空間,但有時候又需要把所有選項都固定展示到窗口上。像這種平鋪的列表控件,Swing給出的控件名稱是ListBox,而JavaFX提供了列表視圖ListView。在具體編碼運用上,ListView的用法幾乎跟ComboBox一模一樣,二者的列表項擁有相同的數據來源,同樣調用setStyle方法來設置各項字體,而且列表項的選擇監聽器也保持一致,唯一的區別便是控件名稱由ComboBox改成了ListView。
既然ListView的用法與ComboBox雷同,這里就不再羅嗦了,仍舊以快餐列表為例,且看下面的ListView使用代碼片段:

	// 獲取列表的界面
	private void getListView(BorderPane borderPane) {
		VBox vbox = new VBox(); // 創建一個垂直箱子
		// 初始化快餐列表
		List<String> snackList = Arrays.asList("魚香肉絲飯", "香菇滑雞飯", "黑椒牛排飯",
				"梅菜扣肉飯", "糖醋里脊飯", "紅燒排骨飯", "台式鹵肉飯");
		// 把清單對象轉換為JavaFX控件能夠識別的數據對象
		ObservableList<String> obList = FXCollections.observableArrayList(snackList);
		ListView<String> listView = new ListView<String>(obList); // 依據指定數據創建列表視圖
		//listView.setItems(obList); // 設置列表視圖的數據來源
		listView.setPrefSize(400, 180); // 設置列表視圖的推薦寬高
		Label label = new Label("這里查看點餐結果"); // 創建一個標簽
		label.setWrapText(true); // 設置標簽文本是否支持自動換行
		vbox.getChildren().addAll(listView, label); // 把列表和標簽一起加到垂直箱子上
		// 設置列表視圖的選擇監聽器
		listView.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", 
						listView.getSelectionModel().getSelectedIndex(), 
						listView.getSelectionModel().getSelectedItem().toString());
				label.setText(desc); // 在標簽上顯示當前選中的文本項
			}
		});
		borderPane.setCenter(vbox); // 把垂直箱子放到邊界窗格的中央
	}

 

運行包含以上代碼的測試程序,在彈出的窗口中單擊按鈕“顯示列表”,界面中央展示了平鋪直敘的快餐列表視圖,正如下面左圖所示。單擊列表中的某種快餐,窗口下方會顯示當前的選擇結果,此時界面效果如下面右圖所示。


盡管ListView能夠將所有選項羅列在界面上,可是每行僅僅顯示當前選項的文本,無法展現更豐富的組合信息。比如餐廳的點餐窗口,除了快餐名稱,還應展示快餐價格,如此一來,整個快餐列表更像是一份表格,不但分行而且分列,才顯得井然有序。為此JavaFX提供了對應的表格控件名叫TableView,不過因為表格內嵌了結構化信息,所以表格內容需要特制的數據實體。就快餐的數據結構而言,假設它由序號、快餐名稱、快餐價格這三個字段組成,則要預先定義如下所示的快餐信息類:

//定義快餐類
public class Snack {
	private SimpleStringProperty xuhao; // 序號
	private SimpleStringProperty name; // 快餐名稱
	private SimpleStringProperty price; // 快餐價格

	public Snack(String xuhao, String name, String price) {
		this.xuhao = new SimpleStringProperty(xuhao);
		this.name = new SimpleStringProperty(name);
		this.price = new SimpleStringProperty(price);
	}

	public String getXuhao() { // 獲取序號
		return xuhao.get();
	}
	public void setXuhao(String xuhao) { // 設置序號
		this.xuhao.set(xuhao);
	}
	public String getName() { // 獲取快餐名稱
		return name.get();
	}
	public void setName(String name) { // 設置快餐名稱
		this.name.set(name);
	}
	public String getPrice() { // 獲取快餐價格
		return price.get();
	}
	public void setPrice(String price) { // 設置快餐價格
		this.price.set(price);
	}
}

注意上面定義的快餐各字段屬性,它們的數據類型為表格專用的SimpleStringProperty,只有該類型的數據才會自動填充到表格單元中。

定義好了快餐信息類,接下來再操作表格控件TableView,使用該控件主要包括下列兩個步驟:
1、指定表格視圖的數據來源
首先創建快餐列表的清單對象,並將其轉換為JavaFX能夠識別的ObservableList對象,然后依據這個數據對象創建表格視圖,相應的代碼片段示例如下:

		// 創建表格的內容清單
		List<Snack> snackList = Arrays.asList(
				new Snack("1", "魚香肉絲飯", "16"),
				new Snack("2", "香菇滑雞飯", "18"),
				new Snack("3", "黑椒牛排飯", "20"),
				new Snack("4", "梅菜扣肉飯", "17"),
				new Snack("5", "糖醋里脊飯", "19"),
				new Snack("6", "紅燒排骨飯", "17"),
				new Snack("7", "台式鹵肉飯", "15"));
		// 把清單對象轉換為JavaFX控件能夠識別的數據對象
		ObservableList<Snack> obList = FXCollections.observableArrayList(snackList);
		TableView<Snack> tableView = new TableView<Snack>(obList); // 依據指定數據創建表格視圖

 

2、創建各列的表頭,以及各列關聯的對象屬性
前一步的數據來源只包含表格的單元內容,不包括表頭的標題行。標題行需要另外通過TableColumn聲明,表格有多少列,就得聲明多少個TableColumn對象,該對象不但規定了當列的標題文字,還規定了當列的內容取自哪個屬性,屬性名稱與第一步數據對象的字段名稱保持一致。以快餐信息為例,快餐對象擁有序號、快餐名稱、快餐價格三個字段,則要給快餐表格分配三個列,且這三列的單元值分別取自Snack類的三個字段(xuhao、name、price)。於是編寫表頭及其關聯屬性的代碼例子如下:

		TableColumn firstColumn = new TableColumn("序號"); // 創建一個表格列
		firstColumn.setMinWidth(100); // 設置列的最小寬度
		// 設置該列取值對應的屬性名稱。此處序號列要展示Snack元素的xuhao屬性值
		firstColumn.setCellValueFactory(new PropertyValueFactory<>("xuhao"));
		TableColumn secondColumn = new TableColumn("快餐名稱"); // 創建一個表格列
		secondColumn.setMinWidth(200); // 設置列的最小寬度
		// 設置該列取值對應的屬性名稱。此處名稱列要展示Snack元素的name屬性值
		secondColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
		TableColumn thirdColumn = new TableColumn("快餐價格"); // 創建一個表格列
		thirdColumn.setMinWidth(110); // 設置列的最小寬度
		// 設置該列取值對應的屬性名稱。此處價格列要展示Snack元素的price屬性值
		thirdColumn.setCellValueFactory(new PropertyValueFactory<>("price"));
		// 把幾個標題列一齊添加到表格視圖
		tableView.getColumns().addAll(firstColumn, secondColumn, thirdColumn);

把上述兩個步驟加以整合,形成完整的表格操作過程,合並后的表格視圖調用代碼如下所示:

	// 獲取表格的界面
	private void getTableView(BorderPane borderPane) {
		VBox vbox = new VBox(); // 創建一個垂直箱子
		// 創建表格的內容清單
		List<Snack> snackList = Arrays.asList(
				new Snack("1", "魚香肉絲飯", "16"),
				new Snack("2", "香菇滑雞飯", "18"),
				new Snack("3", "黑椒牛排飯", "20"),
				new Snack("4", "梅菜扣肉飯", "17"),
				new Snack("5", "糖醋里脊飯", "19"),
				new Snack("6", "紅燒排骨飯", "17"),
				new Snack("7", "台式鹵肉飯", "15"));
		// 把清單對象轉換為JavaFX控件能夠識別的數據對象
		ObservableList<Snack> obList = FXCollections.observableArrayList(snackList);
		TableView<Snack> tableView = new TableView<Snack>(obList); // 依據指定數據創建表格視圖
		//tableView.setItems(obList); // 設置表格視圖的數據來源
		tableView.setPrefSize(400, 210); // 設置表格視圖的推薦寬高
		TableColumn firstColumn = new TableColumn("序號"); // 創建一個表格列
		firstColumn.setMinWidth(100); // 設置列的最小寬度
		// 設置該列取值對應的屬性名稱。此處序號列要展示Snack元素的xuhao屬性值
		firstColumn.setCellValueFactory(new PropertyValueFactory<>("xuhao"));
		TableColumn secondColumn = new TableColumn("快餐名稱"); // 創建一個表格列
		secondColumn.setMinWidth(200); // 設置列的最小寬度
		// 設置該列取值對應的屬性名稱。此處名稱列要展示Snack元素的name屬性值
		secondColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
		TableColumn thirdColumn = new TableColumn("快餐價格"); // 創建一個表格列
		thirdColumn.setMinWidth(110); // 設置列的最小寬度
		// 設置該列取值對應的屬性名稱。此處價格列要展示Snack元素的price屬性值
		thirdColumn.setCellValueFactory(new PropertyValueFactory<>("price"));
		// 把幾個標題列一齊添加到表格視圖
		tableView.getColumns().addAll(firstColumn, secondColumn, thirdColumn);
		vbox.getChildren().add(tableView); // 把表格加到垂直箱子上
		borderPane.setCenter(vbox); // 把垂直箱子放到邊界窗格的中央
	}

 

運行包含以上代碼的測試程序,在彈出的窗口中單擊按鈕“顯示表格”,界面上呈現了一個內容豐富的快餐表格,具體效果如下圖所示。

 



更多Java技術文章參見《Java開發筆記(序)章節目錄


免責聲明!

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



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