User interface 如何在JavaFX中创建多列组合框?
我正在尝试创建一个组合框,在其下拉菜单中显示多列 下面是一个屏幕截图,显示了我希望它的外观: 有什么建议吗 我脑海中唯一的解决方案是通过扩展User interface 如何在JavaFX中创建多列组合框?,user-interface,javafx,combobox,User Interface,Javafx,Combobox,我正在尝试创建一个组合框,在其下拉菜单中显示多列 下面是一个屏幕截图,显示了我希望它的外观: 有什么建议吗 我脑海中唯一的解决方案是通过扩展ComboBox并使用多列对其进行自定义来创建自定义容器 但是JavaFX是否为我提供了创建自定义UI容器的选项 如何创建自定义UI容器以及如何在FXML中使用它?您不需要扩展组合框来创建类似的布局。相反,您只需要提供自己的CellFactory的实现 通过创建自定义的单元格工厂,您可以通过提供自己的列表单元格(在下拉菜单中实际可选择的项目)来控制组合框中
ComboBox
并使用多列对其进行自定义来创建自定义容器
但是JavaFX是否为我提供了创建自定义UI容器的选项
如何创建自定义UI容器以及如何在FXML中使用它?您不需要扩展组合框来创建类似的布局。相反,您只需要提供自己的
CellFactory的实现
通过创建自定义的单元格工厂
,您可以通过提供自己的列表单元格
(在下拉菜单中实际可选择的项目)来控制组合框
中项目的显示方式
我确信有很多方法可以实现这一点,但在本例中,我将使用GridPane
作为我的ListCell
的根布局
下面的完整示例也有注释:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
// List of sample Persons
ObservableList<Person> persons = FXCollections.observableArrayList();
persons.addAll(
new Person("Maria Anders", "Sales Representative", "Zurich"),
new Person("Ana Trujillo", "Owner", "Sydney"),
new Person("Thomas Hardy", "Order Administrator", "Dallas")
);
// Create a simple ComboBox of Persons
ComboBox<Person> cboPersons = new ComboBox<>();
cboPersons.setItems(persons);
// We need a StringConverter in order to ensure the selected item is displayed properly
// For this sample, we only want the Person's name to be displayed
cboPersons.setConverter(new StringConverter<Person>() {
@Override
public String toString(Person person) {
return person.getName();
}
@Override
public Person fromString(String string) {
return null;
}
});
// Provide our own CellFactory to control how items are displayed
cboPersons.setCellFactory(cell -> new ListCell<Person>() {
// Create our layout here to be reused for each ListCell
GridPane gridPane = new GridPane();
Label lblName = new Label();
Label lblTitle = new Label();
Label lblLocation = new Label();
// Static block to configure our layout
{
// Ensure all our column widths are constant
gridPane.getColumnConstraints().addAll(
new ColumnConstraints(100, 100, 100),
new ColumnConstraints(100, 100, 100),
new ColumnConstraints(100, 100, 100)
);
gridPane.add(lblName, 0, 1);
gridPane.add(lblTitle, 1, 1);
gridPane.add(lblLocation, 2, 1);
}
// We override the updateItem() method in order to provide our own layout for this Cell's graphicProperty
@Override
protected void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (!empty && person != null) {
// Update our Labels
lblName.setText(person.getName());
lblTitle.setText(person.getTitle());
lblLocation.setText(person.getLocation());
// Set this ListCell's graphicProperty to display our GridPane
setGraphic(gridPane);
} else {
// Nothing to display here
setGraphic(null);
}
}
});
// Add the ComboBox to the scene
root.getChildren().addAll(
new Label("Select Person:"),
cboPersons
);
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sample");
primaryStage.show();
}
}
// Simple Person class to represent our...Persons
class Person {
private final StringProperty name = new SimpleStringProperty();
private final StringProperty title = new SimpleStringProperty();
private final StringProperty location = new SimpleStringProperty();
Person(String name, String title, String location) {
this.name.set(name);
this.title.set(title);
this.location.set(location);
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
public String getTitle() {
return title.get();
}
public void setTitle(String title) {
this.title.set(title);
}
public StringProperty titleProperty() {
return title;
}
public String getLocation() {
return location.get();
}
public void setLocation(String location) {
this.location.set(location);
}
public StringProperty locationProperty() {
return location;
}
}
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.geometry.Insets;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.ComboBox;
导入javafx.scene.control.Label;
导入javafx.scene.control.ListCell;
导入javafx.scene.layout.ColumnConstraints;
导入javafx.scene.layout.GridPane;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
公共类主扩展应用程序{
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
公共无效开始(阶段primaryStage){
//简单接口
VBox根=新的VBox(10);
根部设置对齐(位置中心);
根。设置填充(新插图(10));
//抽样人员名单
ObservableList persons=FXCollections.observableArrayList();
人名:addAll(
新人(“Maria Anders”、“销售代表”、“苏黎世”),
新人(“安娜·特鲁希略”、“所有者”、“悉尼”),
新人(“托马斯·哈代”、“订单管理员”、“达拉斯”)
);
//创建一个简单的人员组合框
ComboBox cboPersons=新ComboBox();
c运营商设置项目(人);
//我们需要一个StringConverter,以确保正确显示所选项目
//对于此示例,我们只希望显示此人的姓名
cOperson.setConverter(新的StringConverter(){
@凌驾
公共字符串toString(Person){
返回person.getName();
}
@凌驾
公共人物fromString(String){
返回null;
}
});
//提供我们自己的CellFactory来控制项目的显示方式
cOperson.setCellFactory(单元格->新列表单元格(){
//在这里创建我们的布局,以便为每个ListCell重用
GridPane GridPane=新建GridPane();
Label lblName=新标签();
Label lblTitle=新标签();
Label lblLocation=新标签();
//静态块来配置我们的布局
{
//确保我们所有的列宽都是恒定的
gridPane.getColumnConstraints().addAll(
新列约束(100100100),
新列约束(100100100),
新列约束(100100100)
);
add(lblName,0,1);
添加(lblTitle,1,1);
添加(lballocation,2,1);
}
//我们重写updateItem()方法,以便为此单元格的graphicProperty提供我们自己的布局
@凌驾
受保护的void updateItem(Person,布尔值为空){
super.updateItem(person,空);
如果(!empty&&person!=null){
//更新我们的标签
lblName.setText(person.getName());
lblTitle.setText(person.getTitle());
lblLocation.setText(person.getLocation());
//设置此ListCell的graphicProperty以显示我们的GridPane
设置图形(网格窗格);
}否则{
//这里没什么可展示的
设置图形(空);
}
}
});
//将组合框添加到场景中
root.getChildren().addAll(
新标签(“选择人员:”),
C操作员
);
//上台
primaryStage.setScene(新场景(根));
初级阶段。设置标题(“样本”);
primaryStage.show();
}
}
//简单的Person类来代表我们的…Person
班主任{
私有最终StringProperty名称=新SimpleStringProperty();
private final StringProperty title=新SimpleStringProperty();
私有最终StringProperty位置=新SimpleStringProperty();
人员(字符串名称、字符串标题、字符串位置){
this.name.set(name);
此.title.set(title);
此.location.set(位置);
}
公共字符串getName(){
返回name.get();
}
公共void集合名(字符串名){
this.name.set(name);
}
公共字符串属性nameProperty(){
返回名称;
}
公共字符串getTitle(){
返回title.get();
}
公共无效集合标题(字符串标题){
此.title.set(title);
}
公共财产所有权{
返回标题;
}
公共字符串getLocation(){
返回位置。