Как создать многоколоночный Combobox в JavaFX? - PullRequest
2 голосов
/ 08 октября 2019

Я пытаюсь создать ComboBox, который отображает несколько столбцов в выпадающем меню.

Вот снимок экрана, который показывает, как я хочу, чтобы он выглядел:

MultiColumn ComboBox

Есть предложения?

Единственное решение, которое у меня в голове, - это создать собственный контейнер, расширив ComboBox и настроив его с несколькими столбцами.

Но предоставляет ли JavaFX возможность создания контейнера пользовательского интерфейса?

Как создать контейнер пользовательского интерфейса и как использовать его в FXML?

1 Ответ

5 голосов
/ 08 октября 2019

Вам не нужно расширять ComboBox, чтобы создать похожий макет. Вместо этого вам просто нужно предоставить собственную реализацию CellFactory.

. Создав пользовательский CellFactory, вы можете управлять отображением элементов в вашем ComboBox, предоставив свой собственный Listcell(элемент, который на самом деле можно выбрать в раскрывающемся меню).

Я уверен, что есть много способов сделать это, но для этого примера я собираюсь использовать GridPane в качестве корневого макета дляmy 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;
    }
}

Результаты:

screenshot

...