【问题标题】:How to create a multi-column Combobox in JavaFX?如何在 JavaFX 中创建多列组合框?
【发布时间】:2020-02-05 17:36:06
【问题描述】:

我正在尝试创建一个在其下拉菜单中显示多列的ComboBox

这是一个屏幕截图,显示了我希望它的外观:

有什么建议吗?

我想到的唯一解决方案是通过扩展 ComboBox 并使用多列自定义它来创建自定义容器。

但是 JavaFX 是否甚至为我提供了创建自定义 UI 容器的选项?

如何创建自定义 UI 容器以及如何在 FXML 中使用它?

【问题讨论】:

  • 您不需要自定义ComboBox,只需自定义CellFactory。你可以在 StackOverflow 上找到几个关于这样做的现有问题。使用自定义CellFactory,您可以将任何Node(包括整个布局)用于下拉项。
  • 但是,您不能在 FXML 中定义它。
  • @Zephyr 好的,谢谢。我来看看 CellFactory。

标签: user-interface javafx combobox


【解决方案1】:

您无需扩展 ComboBox 即可创建类似的布局。相反,您只需要提供自己的 CellFactory 实现即可。

通过创建自定义CellFactory,您可以通过提供自己的Listcell(实际上可以在下拉菜单中选择的项目)来控制ComboBox 中项目的显示方式。

我确信有很多方法可以实现这一点,但对于这个示例,我将使用GridPane 作为我的ListCell 的根布局。

下面的完整示例也包含 cmets:

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 专业人士 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多