JavaFx 属性 与屏幕上的多个对象绑定

JavaFx property binding with multiple objects on on screen

我使用带有 属性 绑定的 JavaFx。 我得到了一个对象 'Person',其属性为 'name' 和年龄。 这些对象存储在 ObservableList 中。

属性绑定到 gui 上的标签。当我更改 ListBox 中的人时,右侧的数据也会更改。

带有人员列表的 GUI:

现在轮到我的问题了。 我想在一个 window 上显示所有人,如下图所示。

多人在一个视图中的 GUI:

我该如何处理。我想到了 HBox,但绑定不起作用。

仅供参考:在这里您可以找到我使用的教程。 https://code.makery.ch/library/javafx-tutorial/part1/

这看起来是将 ListView 与自定义 ListCell 实现结合使用的最佳时机。

下面的示例应用程序显示了一个非常基本的应用程序,它在 ListView 中显示每个 Person 对象。我们将提供自己的 ListCell,以便我们可以准确控制每个 Person 的显示方式。

我还添加了个人资料照片只是为了好玩:)


import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
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.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class ListViewDetailSample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // First, let's create our list of Persons
        ObservableList<Person> persons = FXCollections.observableArrayList();
        persons.addAll(
                new Person("John", 34),
                new Person("Cheyenne", 24),
                new Person("Micah", 17),
                new Person("Katelyn", 28)
        );

        // Create a ListView
        ListView<Person> listView = new ListView<>();

        // Bind our list to the ListView
        listView.setItems(persons);

        // Now, for the magic. We'll create our own ListCells for the ListView. This allows us to create a custom
        // layout for each individual cell. For this sample, we'll include a profile picture, the name, and the age.
        listView.setCellFactory(new Callback<ListView<Person>, ListCell<Person>>() {
            @Override
            public ListCell<Person> call(ListView<Person> param) {
                return new ListCell<Person>() {
                    @Override
                    protected void updateItem(Person person, boolean empty) {
                        super.updateItem(person, empty);

                        // Set any empty cells to show nothing
                        if (person == null || empty) {
                            setText(null);
                            setGraphic(null);
                        } else {
                            // Here we can build our layout. We'll use a HBox for our root container
                            HBox cellRoot = new HBox(5);
                            cellRoot.setAlignment(Pos.CENTER_LEFT);
                            cellRoot.setPadding(new Insets(5));

                            // Add our profile picture
                            ImageView imgProfilePic = new ImageView("/sample/user.png");
                            imgProfilePic.setFitHeight(24);
                            imgProfilePic.setFitWidth(24);
                            cellRoot.getChildren().add(imgProfilePic);

                            // A simple Separator between the photo and the details
                            cellRoot.getChildren().add(new Separator(Orientation.VERTICAL));

                            // Now, create a VBox to hold the name and age
                            VBox vBox = new VBox(5);
                            vBox.setAlignment(Pos.CENTER_LEFT);
                            vBox.setPadding(new Insets(5));

                            // Add our Person details
                            vBox.getChildren().addAll(
                                    new Label("Name: " + person.getName()),
                                    new Label("Age: " + person.getAge())
                            );

                            // Add our VBox to the cellRoot
                            cellRoot.getChildren().add(vBox);

                            // Finally, set this cell to display our custom layout
                            setGraphic(cellRoot);
                        }
                    }
                };
            }
        });

        // Now, add our ListView to the root layout
        root.getChildren().add(listView);

        // Show the Stage
        primaryStage.setWidth(450);
        primaryStage.setHeight(400);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

// Simple Person class
class Person {

    private final StringProperty name = new SimpleStringProperty();
    private final IntegerProperty age = new SimpleIntegerProperty();

    public Person(String name, int age) {
        this.name.set(name);
        this.age.set(age);
    }

    public String getName() {
        return name.get();
    }

    public StringProperty nameProperty() {
        return name;
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public int getAge() {
        return age.get();
    }

    public IntegerProperty ageProperty() {
        return age;
    }

    public void setAge(int age) {
        this.age.set(age);
    }
}

The Result:


Without ListView:

如果您不想为此显示使用 ListView,您可以保留另一个 Person 显示列表并将其绑定到您想要的任何容器的子列表:

    // Create a list to hold our individual Person displays
    ObservableList<Node> personDisplays = FXCollections.observableArrayList();

    // Now add a new PersonDisplay to the list for each Person in the personsList
    persons.forEach(person -> personDisplays.add(new PersonDisplay(person)));

    // Bind our personsDisplay list to the children of our root VBox
    Bindings.bindContent(root.getChildren(), personDisplays);

PersonDisplay class:

class PersonDisplay extends HBox {

    public PersonDisplay(Person person) {
        // First, let's configure our root layout
        setSpacing(5);
        setAlignment(Pos.CENTER_LEFT);
        setPadding(new Insets(5));

        // Add our profile picture
        ImageView imgProfilePic = new ImageView("/user.png");
        imgProfilePic.setFitHeight(24);
        imgProfilePic.setFitWidth(24);
        getChildren().add(imgProfilePic);

        // A simple Separator between the photo and the details
        getChildren().add(new Separator(Orientation.VERTICAL));

        // Now, create a VBox to hold the name and age
        VBox vBox = new VBox(5);
        vBox.setAlignment(Pos.CENTER_LEFT);
        vBox.setPadding(new Insets(5));

        // Add our Person details
        vBox.getChildren().addAll(
                new Label("Name: " + person.getName()),
                new Label("Age: " + person.getAge())
        );

        // Add our VBox to the layout
        getChildren().add(vBox);
    }
}

The Result: