翻译自 Combo Box
本章介绍如何在JavaFX应用程序中使用组合框。它讨论了可编辑和不可编辑的组合框,教您如何跟踪可编辑组合框中的更改并处理它们上的事件,并解释如何使用单元工厂来更改组合框的默认实现。
组合框是用户界面的典型元素,使用户可以选择多个选项之一。当要显示的项目数超过某个限制时,组合框很有用,因为它可以将滚动添加到下拉列表中,与选择框不同。如果项目数量不超过某个限制,开发人员可以决定组合框或选择框是否更符合他们的需求。
您可以使用ComboBox
JavaFX API 的类在JavaFX应用程序中创建组合框。图14-1显示了具有两个组合框的应用程序。
图14-1两个组合框的应用
创建组合框
当创建一个组合框,你必须实例化ComboBox
类,并定义项目作为观察的名单,就像如其他UI控件ChoiceBox
,ListView
以及TableView
。例14-1设置构造函数中的项。
示例14-1创建带有可观察列表的组合框
ObservableList<String> options = FXCollections.observableArrayList("Option 1","Option 2","Option 3");
final ComboBox comboBox = new ComboBox(options);
另一种可能性是使用空构造函数创建一个组合框并setItems
在其上调用方法,如下所示:comboBox.setItems(options);
将组合框添加到应用程序场景后,它将显示在用户界面中,如图14-2所示。
图14-2包含三个项目的组合框
您可以随时使用新值补充项目列表。例14-2通过向comboBox控件添加另外三个项来实现此任务。
示例14-2将项添加到组合框
comboBox.getItems().addAll("Option 4","Option 5","Option 6"
);
本ComboBox
类提供方便的属性和方法与组合框使用。
您可以使用该setValue
方法指定组合框中选定的项目。在对象setValue
上调用方法时ComboBox
,selectionModel
即使该值不在组合框项目列表中,属性的选定项也会更改为此值。如果项目列表随后更改为包含此值,则会选择相应的项目。
同样,您可以通过调用getValue
方法获取所选项的值。当用户选择项目时,selectionModel
属性的选定项目和组合框value
属性都更新为新值。
您还可以在ComboBox
显示时限制下拉列表中的可见行数。以下代码行可以显示comboBox控件的三个项目:comboBox.setVisibleRowCount(3)
作为调用此方法的结果,可见行数限制为3,并出现滚动条(如图14-3所示)。
图14-3设置组合框的可见行数
尽管ComboBox
该类具有通用符号并且允许用户使用各种类型的项填充它,但不要使用Node
(或任何子类)作为类型。因为场景图概念意味着只有一个Node
对象可以位于应用程序场景的一个位置,所以从ComboBox
项列表中删除所选项。当选择更改时,先前选择的项目将返回到列表,并删除新选择。要防止出现这种情况,请使用单元工厂机制和API文档中描述的解决方案。当您需要更改对象的初始行为或外观时,单元工厂机制特别有用ComboBox
。
ComboBoxSample应用程序旨在说明如何在典型的电子邮件界面中使用组合框。例14-3创建了一个这样的界面,其中使用两个组合框来选择电子邮件收件人和邮件的优先级。
示例14-3创建组合框并将其添加到场景中
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;public class ComboBoxSample extends Application {public static void main(String[] args) {launch(args);}final Button button = new Button ("Send");final Label notification = new Label ();final TextField subject = new TextField("");final TextArea text = new TextArea ("");String address = " ";@Override public void start(Stage stage) {stage.setTitle("ComboBoxSample");Scene scene = new Scene(new Group(), 450, 250);final ComboBox emailComboBox = new ComboBox();emailComboBox.getItems().addAll("jacob.smith@example.com","isabella.johnson@example.com","ethan.williams@example.com","emma.jones@example.com","michael.brown@example.com" );final ComboBox priorityComboBox = new ComboBox();priorityComboBox.getItems().addAll("Highest","High","Normal","Low","Lowest" ); priorityComboBox.setValue("Normal");GridPane grid = new GridPane();grid.setVgap(4);grid.setHgap(10);grid.setPadding(new Insets(5, 5, 5, 5));grid.add(new Label("To: "), 0, 0);grid.add(emailComboBox, 1, 0);grid.add(new Label("Priority: "), 2, 0);grid.add(priorityComboBox, 3, 0);grid.add(new Label("Subject: "), 0, 1);grid.add(subject, 1, 1, 3, 1); grid.add(text, 0, 2, 4, 1);grid.add(button, 0, 3);grid.add (notification, 1, 3, 3, 1);Group root = (Group)scene.getRoot();root.getChildren().add(grid);stage.setScene(scene);stage.show();}
}
例14-3中的两个组合框都使用getItems
和addAll
方法来添加项目。编译并运行此代码时,它会生成如图14-4所示的应用程序窗口。
图14-4电子邮件收件人和优先级组合框
可编辑的组合框
通常,电子邮件客户端应用程序使用户能够从地址簿中选择收件人并键入新地址。可编辑的组合框非常适合此任务。使用类的setEditable(true)
方法ComboBox
使组合框可编辑。使用此setPromptText
方法,您可以指定在未执行选择时显示在组合框编辑区域中的文本。检查示例14-4中的应用程序的修改代码。粗线是对例14-3的补充。
示例14-4在可编辑的组合框中处理新键入的值
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;public class ComboBoxSample extends Application {public static void main(String[] args) {launch(args);}final Button button = new Button ("Send");final Label notification = new Label ();final TextField subject = new TextField("");final TextArea text = new TextArea ("");String address = " ";@Override public void start(Stage stage) {stage.setTitle("ComboBoxSample");Scene scene = new Scene(new Group(), 450, 250);final ComboBox emailComboBox = new ComboBox();emailComboBox.getItems().addAll("jacob.smith@example.com","isabella.johnson@example.com","ethan.williams@example.com","emma.jones@example.com","michael.brown@example.com" );emailComboBox.setPromptText("Email address");emailComboBox.setEditable(true); emailComboBox.valueProperty().addListener(new ChangeListener<String>() {@Override public void changed(ObservableValue ov, String t, String t1) { address = t1; } });final ComboBox priorityComboBox = new ComboBox();priorityComboBox.getItems().addAll("Highest","High","Normal","Low","Lowest" ); priorityComboBox.setValue("Normal");button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent e) {//do something}}); GridPane grid = new GridPane();grid.setVgap(4);grid.setHgap(10);grid.setPadding(new Insets(5, 5, 5, 5));grid.add(new Label("To: "), 0, 0);grid.add(emailComboBox, 1, 0);grid.add(new Label("Priority: "), 2, 0);grid.add(priorityComboBox, 3, 0);grid.add(new Label("Subject: "), 0, 1);grid.add(subject, 1, 1, 3, 1); grid.add(text, 0, 2, 4, 1);grid.add(button, 0, 3);grid.add (notification, 1, 3, 3, 1);Group root = (Group)scene.getRoot();root.getChildren().add(grid);stage.setScene(scene);stage.show();}
}
除了编辑功能外emailComboBox
,此代码片段还实现了此控件的事件处理。新键入或选择的值存储在address
变量中。当用户按“发送”按钮时,将显示包含电子邮件地址的通知。
图14-5显示了用户编辑Jacob Smith的电子邮件地址并将其更改为greg.smith@example.com的时刻。
图14-5编辑电子邮件地址
按下发送按钮后,所有控件都将返回其默认状态。该clear
方法被称为上TextField
和TextArea
对象和null
值设置为组合框中选定的项目。图14-6显示了按下发送按钮后的时刻。
图14-6按下发送按钮后的用户界面
将Cell Factories应用于组合框
您可以使用单元工厂机制来更改组合框的默认行为或外观。例14-5创建了一个单元工厂并将其应用于优先级组合框以突出显示具有特殊颜色的优先级类型。
示例14-5为优先级组合框实现单元工厂
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;public class ComboBoxSample extends Application {public static void main(String[] args) {launch(args);}final Button button = new Button ("Send");final Label notification = new Label ();final TextField subject = new TextField("");final TextArea text = new TextArea ("");String address = " ";@Override public void start(Stage stage) {stage.setTitle("ComboBoxSample");Scene scene = new Scene(new Group(), 450, 250);final ComboBox emailComboBox = new ComboBox();emailComboBox.getItems().addAll("jacob.smith@example.com","isabella.johnson@example.com","ethan.williams@example.com","emma.jones@example.com","michael.brown@example.com" );emailComboBox.setPromptText("Email address");emailComboBox.setEditable(true); emailComboBox.valueProperty().addListener(new ChangeListener<String>() {@Override public void changed(ObservableValue ov, String t, String t1) { address = t1; } });final ComboBox priorityComboBox = new ComboBox();priorityComboBox.getItems().addAll("Highest","High","Normal","Low","Lowest" ); priorityComboBox.setValue("Normal");priorityComboBox.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {@Override public ListCell<String> call(ListView<String> param) {final ListCell<String> cell = new ListCell<String>() {{super.setPrefWidth(100);} @Override public void updateItem(String item, boolean empty) {super.updateItem(item, empty);if (item != null) {setText(item); if (item.contains("High")) {setTextFill(Color.RED);}else if (item.contains("Low")){setTextFill(Color.GREEN);}else {setTextFill(Color.BLACK);}}else {setText(null);}}};return cell;}});button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent e) {if (emailComboBox.getValue() != null && !emailComboBox.getValue().toString().isEmpty()){notification.setText("Your message was successfully sent"+ " to " + address); emailComboBox.setValue(null);if (priorityComboBox.getValue() != null && !priorityComboBox.getValue().toString().isEmpty()){priorityComboBox.setValue(null);}subject.clear();text.clear();}else {notification.setText("You have not selected a recipient!"); }}});GridPane grid = new GridPane();grid.setVgap(4);grid.setHgap(10);grid.setPadding(new Insets(5, 5, 5, 5));grid.add(new Label("To: "), 0, 0);grid.add(emailComboBox, 1, 0);grid.add(new Label("Priority: "), 2, 0);grid.add(priorityComboBox, 3, 0);grid.add(new Label("Subject: "), 0, 1);grid.add(subject, 1, 1, 3, 1); grid.add(text, 0, 2, 4, 1);grid.add(button, 0, 3);grid.add (notification, 1, 3, 3, 1);Group root = (Group)scene.getRoot();root.getChildren().add(grid);stage.setScene(scene);stage.show();}
}
细胞工厂生产ListCell
物体。每个单元格都与一个组合框项目相关联。通过该setPrefWidth
方法设置每个组合框项的宽度。该updateItem
方法为“高”和“最高”项设置红色,为“低”和“最低”项设置绿色,并将“正常”项设置为黑色。
图14-7显示了应用示例14-5中的单元工厂后优先级组合框的项目。
图14-7修改了优先级组合框
您可以ComboBox
通过应用CSS样式或视觉效果进一步增强控件的外观。
相关的API文档
-
ComboBox
-
ComboBoxBase
-
ListView
-
ListCell
-
Button