本章介绍如何在应用中使用组合框,我们将会讲到可修改和不可修改的组合框,告诉我们怎样跟踪可修改组合框的变化以及处理它们的事件,并且还会讲到如何利用单元格工厂修改默认的实现方式。
组合框是用户界面典型的元素,可以让用户从几个选项中选择一个。和选择框不同,当元素的个数超过限制的时候组合框式很有用的,因为可以为下拉列表提供滚动条。当元素个数没有超过限制的时候,开发者可以根据需要选择组合框和选择框。
我们可以利用ComboBox来创建组合框。
使用单元格工厂
当创建组合框的时候,我们需要创建一个ComboBox的实例。并且定义元素封装到一个可观察的list中。就像其他的UI控件一样,比如:ChoiceBox,ListView和TableView。
ObservableList<String> options =
FXCollections.observableArrayList(
"Option 1",
"Option 2",
"Option 3"
);
final ComboBox comboBox = new ComboBox(options);
在任何时候,你都可以增加组合框的值。像下面这样:
comboBox.getItems().addAll(
"Option 4",
"Option 5",
"Option 6"
);
ComboBox提供了方便的属性和方法供我们使用。
我们可以使用setValue方法来选中组合框中的某一项元素。如果你调用了setValue方法,那么选择项就会改变,即使这个值不存在。如果存在那么相应的项会被选上。
我们也可以通过getValue方法来获得选中项的值。当用户选中某一项时,SelectionModel属性和组合框的值会同时更新。
你也可以限制组合框可看到的元素的个数。通过setVisibleRowCount(3)方法我们只可以在下拉框中看到3个元素,并且出现了滚动条。
尽管ComboBox可以让用户使用不同的类型,但不是Node类型。因为场景图的概念就暗示了只有Node对象才能存在场景中,选中的项将会从组合框列表中删除。当选择项改变的时候,之前被删除的选择项重新出现在列表中,而新选择的项被删除。为了阻止这种情况,我们可以是用单元格工厂机制。如果你想改变组合框和默认方式或者要控制组合框表现方式的时候单元格工厂是很有用的。
下面的例子展示了组合框的使用。
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(), 500, 270);
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();
}
}
可编辑的组合框
我们可以是用setEditable(true)方法来使得组合框式可编辑的。
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.Event;
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(), 500, 270);
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.setOnAction((Event ev) -> {
address =
emailComboBox.getSelectionModel().getSelectedItem().toString();
});
final ComboBox priorityComboBox = new ComboBox();
priorityComboBox.getItems().addAll(
"Highest",
"High",
"Normal",
"Low",
"Lowest"
);
priorityComboBox.setValue("Normal");
button.setOnAction((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();
}
}
使用单元格工厂
我们可以是用单元格工厂来改变组合框的默认行为以及表现方式。
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.Event;
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(), 500, 270);
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.setOnAction((Event ev) -> {
address =
emailComboBox.getSelectionModel().getSelectedItem().toString();
});
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((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();
}
}