sym*_*yri 1 java combobox javafx
我目前正在使用 Java 和 JavaFX 开发一款游戏。我正在使用 JavaFX ComboBox。
下面的例子应该可以解释我的问题。
假设我有一个“动物”类,其属性为“名称”、“年龄”和“颜色”。
第一个文件:
public class Animal {
private String name;
private int age;
private String color;
public Animal(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想为我创建的每只动物创建一个组合框。
第二个文件:
ComboBox<Animal> comboBoxAnimal = new ComboBox();
ObservableList<Animal> comboBoxItems = FXCollections.observableArrayList();
Animal dog = new Animal("Liam", 2, "Brown");
Animal cat = new Animal("Emily", 5, "Gray");
Animal bird = new Animal("Kian", 3, "Green");
comboBoxItems.addAll(dog, cat, bird);
comboBoxAnimal.setItems(comboBoxItems);
Run Code Online (Sandbox Code Playgroud)
目前我只得到“Animal@xxxxxxxx”,这是可以理解的,因为我有一个动物组合框,但只想显示名称(字符串)。
只是简单地创建一个ComboBox<String>并不能解决问题,因为我需要一个Combobox<Animal>.
我怎样才能得到一个Combobox<Animal>但是因为元素只显示每个动物的名字?
感谢您的反馈意见 :)
两种选择:
本答案中使用的单元工厂和字符串转换器示例产生相同的输出:
细胞工厂实施
使用细胞工厂,就像这个答案一样:
链接的答案适用于 ListView,但 ComboBox 类似,TableView 或其他依赖单元工厂进行显示的虚拟化控件也是如此。
要为组合框下拉列表和按钮配置单元格,请调用setCellFactory和setButtonCell。
这是最灵活的解决方案,并且允许进行超出文本字符串范围的自定义。可以创建图形节点来完全自定义每个组合框单元的视觉表示。
示例代码
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.stage.Stage;
public class AnimalComboApp extends Application {
public record Animal(String name, int age, String color) {}
public static class AnimalCell extends ListCell<Animal> {
@Override
public void updateItem(Animal animal, boolean empty) {
super.updateItem(animal, empty);
if (animal == null || empty) {
setText(null);
} else {
setText(animal.name());
}
}
}
@Override
public void start(Stage stage) throws Exception {
ComboBox<Animal> comboBox = new ComboBox<>();
comboBox.getItems().setAll(
new Animal("Liam", 2, "Brown"),
new Animal("Emily", 5, "Gray"),
new Animal("Kian", 3, "Green")
);
comboBox.setCellFactory(listView -> new AnimalCell());
comboBox.setButtonCell(new AnimalCell());
comboBox.getSelectionModel().select(0);
stage.setScene(new Scene(comboBox));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)
字符串转换器实现
单元工厂定义的替代方法是为 ComboBox 提供 StringConverter ,它可以在字符串和对象之间进行转换。
需要StringConverter和fromString来toString实现,但fromString实现可以返回null,除非您还希望用户能够执行文本编辑来编辑组合框值。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class AnimalComboApp extends Application {
public record Animal(String name, int age, String color) {}
@Override
public void start(Stage stage) throws Exception {
ComboBox<Animal> comboBox = new ComboBox<>();
comboBox.getItems().setAll(
new Animal("Liam", 2, "Brown"),
new Animal("Emily", 5, "Gray"),
new Animal("Kian", 3, "Green")
);
comboBox.setConverter(new StringConverter<>() {
@Override
public String toString(Animal animal) {
return animal.name();
}
@Override
public Animal fromString(String string) {
return null;
}
});
comboBox.getSelectionModel().select(0);
Scene scene = new Scene(comboBox);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)
不使用的选项
toString() 实现
不要覆盖toString()以自定义单元格,这是一种反模式。
用于toString()其他目的,例如列出和调试 Animal 类的所有元素,而是使用适当的方法(例如单元工厂或字符串转换器)来自定义Animal.
将节点放置在组合框列表中
您可能还想尝试将节点直接放入 ComboBox 列表中(例如,在每个 Label 中创建带有对象名称的 Label,然后创建一个ComboBox<Label>)。
不要这样做,正如ComboBox API 文档部分所建议的:“关于将节点插入 ComboBox 项目列表的警告”,它会在您的应用程序中产生错误。