0

I use JavaFx with property binding. I got a object 'Person' with the properties 'name' and age. These objects are stored in a ObservableList.

The properties are bound to labels on the gui. When I change the person in the ListBox the data also change on the right hand side.

GUI with person list: GUI with person list

And now it comes to my problem. I want to disply all persons on one window, like the next picture shows.

GUI with multiple persons on one view: GUI with multiple persons on one view

How can I handle this. I thought about HBox but the binding doesn't work.

FYI: Here you can find the tutorial I used. https://code.makery.ch/library/javafx-tutorial/part1/

2
  • 1
    Hi! Welcome to stack overflow, if your question does not attract answers, check out stackoverflow.com/help/how-to-ask to get good tips on how to get improve it ;) Commented Dec 13, 2018 at 22:49
  • You need to use ListView for this. Commented Dec 14, 2018 at 1:04

1 Answer 1

3

This looks like a perfect time to use a ListView with custom ListCell implementations.

The sample application below shows a very basic application that displays each Person object in a ListView. We will provide our own ListCell so we can control exactly how each Person gets displayed.

I also added a profile photo just for fun :)


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:

screenshot


Without ListView:

If you'd prefer not to use a ListView for this display, you can keep another list of your Person displays and bind that to the children list of whichever container you want:

 // 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:

screenshot 2

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.