12 列表视图
在本章中,您将学习如何在JavaFX应用程序中创建列表。
ListView
类表示一个可滚动的项目列表。在酒店预订系统中,图12-1显示了可用住宿类型的列表。
您可以使用setItems
方法定义列表的项目来填充列表。您还可以通过应用setCellFactory
方法为列表中的项目创建视图。
创建列表视图
在示例12-1中的代码片段实现了列表视图,其中显示了图12-1中的String
项。
示例12-1 创建列表视图控件
ListView<String> list = new ListView<>(); ObservableList<String> items =FXCollections.observableArrayList ( "Single", "Double", "Suite", "Family App"); list.setItems(items);
要更改列表视图控件的大小和高度,使用setPrefHeight
和setPrefWidth
方法。在示例12-2中,将垂直列表限制为100像素宽和70像素高,结果如图12-2所示。
您可以通过将ListView
对象的方向属性设置为Orientation.HORIZONTAL
来使其水平排列。可以使用以下方式完成:list.setOrientation(Orientation.HORIZONTAL)
。与图12-1中相同的项的水平列表显示在图12-3中。
您可以使用SelectionModel
和FocusModel
类来跟踪ListView
对象的选择和焦点状态。使用以下方法组合来获取每个项的当前状态:
-
getSelectionModel().getSelectedIndex()
- 返回单选模式下当前选定项的索引 -
getSelectionModel().getSelectedItem()
- 返回当前选定的项 -
getFocusModel().getFocusedIndex()
- 返回当前焦点项的索引 -
getFocusModel().getFocusedItem()
- 返回当前焦点项
当实例化一个ListView
时,默认使用的SelectionModel
是MultipleSelectionModel
抽象类的一个实现。然而,selectionMode
属性的默认值是SelectionMode.SINGLE
。要在默认的ListView
实例中启用多选功能,请使用以下调用序列:
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
还要注意,MultipleSelectionModel
有selectedItems
和selectedIndices
属性,它们都是可观察的列表,可以监视以检测任何多选。
使用数据填充列表视图
示例12-1展示了最简单的填充列表视图的方法。为了增强列表的功能,你可以使用ListCell
类的特定扩展,如CheckBoxListCell
、ChoiceBoxListCell
、ComboBoxListCell
和TextFieldListCell
,来添加不同类型的数据。这些类为基本的列表单元格提供了额外的功能。通过为这些类实现单元格工厂,开发人员可以直接在列表视图中更改数据。
例如,默认情况下,列表单元格的内容是不可编辑的。然而,ComboBoxListCell
类在列表单元格内部绘制了一个组合框。这个修改使得用户可以通过从组合框中选择来构建一个名称列表,如示例12-3所示。
示例12-3 向列表视图添加ComboBoxListCell项
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.ComboBoxListCell;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ListViewSample extends Application {
public static final ObservableList names =
FXCollections.observableArrayList();
public static final ObservableList data =
FXCollections.observableArrayList();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("List View Sample");
final ListView listView = new ListView(data);
listView.setPrefSize(200, 250);
listView.setEditable(true);
names.addAll(
"Adam", "Alex", "Alfred", "Albert",
"Brenda", "Connie", "Derek", "Donny",
"Lynne", "Myrtle", "Rose", "Rudolph",
"Tony", "Trudy", "Williams", "Zach"
);
for (int i = 0; i < 18; i++) {
data.add("anonym");
}
listView.setItems(data);
listView.setCellFactory(ComboBoxListCell.forListView(names));
StackPane root = new StackPane();
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root, 200, 250));
primaryStage.show();
}
}
示例中的粗体行调用了setCellFactory
方法来重新定义列表单元格的实现。当你编译和运行这个示例时,会产生如图12-4所示的应用窗口。
单元格工厂机制不仅使你能够应用列表单元格的替代实现,还可以帮助你完全自定义单元格的外观。
自定义列表视图的内容
学习以下应用程序,了解如何使用单元格工厂生成列表项。在示例12-4中显示的应用程序创建了一个颜色模式列表。
示例12-4 创建单元格工厂
import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class ListViewSample extends Application { ListView<String> list = new ListView<>(); ObservableList<String> data = FXCollections.observableArrayList( "巧克力", "鲑鱼", "金色", "珊瑚", "暗紫色", "深金色", "浅鲑鱼", "黑色", "玫瑰棕色", "蓝色", "蓝紫色", "棕色"); @Override public void start(Stage stage) { VBox box = new VBox(); Scene scene = new Scene(box, 200, 200); stage.setScene(scene); stage.setTitle("ListViewSample"); box.getChildren().addAll(list); VBox.setVgrow(list, Priority.ALWAYS); list.setItems(data); list.setCellFactory((ListView<String> l) -> new ColorRectCell()); stage.show(); } static class ColorRectCell extends ListCell<String> { @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); Rectangle rect = new Rectangle(100, 20); if (item != null) { rect.setFill(Color.web(item)); setGraphic(rect); } } } public static void main(String[] args) { launch(args); } }
单元格工厂生成ListCell
对象。每个单元格与一个数据项关联,并呈现列表视图的一个“行”。通过setGraphic
方法表示的单元格内容可以包括其他控件、文本、形状或图像。在这个应用程序中,列表单元格显示矩形。
编译和运行该应用程序会产生图12-5中显示的窗口。
您可以滚动列表,选择和取消选择其中的任何项。您还可以扩展此应用程序,将文本标签填充为颜色模式,如下一节所示。
处理列表项选择
将应用程序代码修改为如示例12-5所示,以便在选择特定列表项时处理事件。
示例12-5 处理列表项的事件
import javafx.application.Application; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.scene.text.Font; import javafx.stage.Stage; public class ListViewSample extends Application { ListView<String> list = new ListView<>(); ObservableList<String> data = FXCollections.observableArrayList( "巧克力", "鲑鱼", "黄金", "珊瑚", "暗兰色", "深金色", "浅鲑鱼", "黑色", "玫瑰棕色", "蓝色", "蓝紫色", "棕色"); final Label label = new Label(); @Override public void start(Stage stage) { VBox box = new VBox(); Scene scene = new Scene(box, 200, 200); stage.setScene(scene); stage.setTitle("ListViewSample"); box.getChildren().addAll(list, label); VBox.setVgrow(list, Priority.ALWAYS); label.setLayoutX(10); label.setLayoutY(115); label.setFont(Font.font("Verdana", 20)); list.setItems(data); list.setCellFactory((ListView<String> l) -> new ColorRectCell()); list.getSelectionModel().selectedItemProperty().addListener( (ObservableValue<? extends String> ov, String old_val, String new_val) -> { label.setText(new_val); label.setTextFill(Color.web(new_val)); }); stage.show(); } static class ColorRectCell extends ListCell<String> { @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); Rectangle rect = new Rectangle(100, 20); if (item != null) { rect.setFill(Color.web(item)); setGraphic(rect); } else { setGraphic(null); } } } public static void main(String[] args) { launch(args); } }
addListener
方法用于selectedItemProperty
,创建一个新的监听器来处理选定项的更改。例如,如果选择了暗兰色项,标签将接收到"darkorchid"的标题,并填充相应的颜色。修改后应用程序的输出如图12-6所示。
相关文档