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

时间:2018-12-13 22:43:19

标签: javafx property-binding

我将JavaFx与属性绑定一起使用。 我得到了具有属性“名称”和“年龄”的对象“人员”。 这些对象存储在ObservableList中。

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

带有人员列表的GUI: GUI with person list

现在是我的问题了。 我想在一个窗口上显示所有人,就像下一张照片所示。

在一个视图上有多个人的GUI: GUI with multiple persons on one view

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

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

1 个答案:

答案 0 :(得分:2)

这似乎是将ListView与自定义ListCell实现一起使用的绝佳时机。

下面的示例应用程序显示了一个非常基本的应用程序,它显示了Person中的每个ListView对象。我们将提供自己的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);
    }
}

  

结果:

screenshot


  

没有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 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);
    }
}
  

结果:

screenshot 2