JavaFX8 xaml-like list bindings

I cannot associate a collection with a custom template in fxml. Here is the code how I would do it in xaml:

<ListView ItemsSource="{Binding PersonCollection}"> <StackPanel Orientation="Horizontal"> <Label Content="{Binding FirstName}"></Label> <ListView ItemsSource="{Binding MiddleNames}"> <Label Content="{Binding}"></Label> </ListView> <Label Content="{Binding LastName}"></Label> </StackPanel> </ListView> 

Here is the Model:

 class Person { String FirstName, LastName; String[] MiddleNames; } 

And the layout will look something like this:

 John Ivy Robert Downey Junior Max more middlenames in fact even thousands are possible lastname 

Is it possible to associate an oberservable collection with a custom template? I tried cellfactory but could not wrap my head around as everyone used only strings.

+5
source share
1 answer

I am not 100% sure, this is the answer to your question, since I am completely not familiar with xaml, but I hope this ...

Implementation example

The sample works by setting the model object (Person) to the FXML loader namespace, which allows you to use the binding expression in FXML to bind to the properties of the object.

There are several names in the model at first, and you can change the linked list in the model using the add and remove buttons to add or remove a few more canned names in the list.

sample image

All code is sent in a package called sample.names.

display_name.fxml

 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.ListView?> <?import javafx.scene.layout.HBox?> <?import javafx.geometry.Insets?> <?import javafx.scene.layout.VBox?> <?import javafx.scene.control.Button?> <VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.names.NameDisplayController"> <HBox prefHeight="150.0" prefWidth="220.0" spacing="5.0" > <children> <Label fx:id="firstNameLabel" text="${person.firstName}" /> <ListView fx:id="middleNameList" prefWidth="100.0" items = "${person.middleNames}" /> <Label fx:id="lastNameLabel" text="${person.lastName}" /> </children> <padding> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> </padding> </HBox> <HBox alignment="CENTER" spacing="30.0"> <children> <Button mnemonicParsing="false" onAction="#addName" text="Add" /> <Button mnemonicParsing="false" onAction="#removeName" text="Remove" /> </children> <padding> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> </padding> </HBox> </VBox> 

NameDisplayApp.java

 import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.layout.Pane; import javafx.stage.Stage; import java.io.IOException; public class NameDisplayApp extends Application { @Override public void start(Stage stage) throws IOException { Person person = new Person( "Bruce", new String[] { "Simon", "Larry" }, "Banner" ); FXMLLoader loader = new FXMLLoader( getClass().getResource( "name-display.fxml" ) ); loader.getNamespace().put( "person", person ); Pane pane = loader.load(); NameDisplayController controller = loader.getController(); controller.setPerson(person); stage.setScene(new Scene(pane)); stage.show(); } public static void main(String[] args) { launch(args); } } 

NameDisplayController.java

 import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; public class NameDisplayController { private Person person; private ObservableList<String> sampleNames = FXCollections.observableArrayList( "George", "Henry", "Wallace" ); public void setPerson(Person person) { this.person = person; } public void addName(ActionEvent actionEvent) { if (!sampleNames.isEmpty()) { person.getMiddleNames().add( sampleNames.remove(0) ); } } public void removeName(ActionEvent actionEvent) { if (!person.getMiddleNames().isEmpty()) { sampleNames.add( person.getMiddleNames().remove(0) ); } } } 

Person.java

 import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; public class Person { public StringProperty firstName; public StringProperty lastName; private ObservableList<String> middleNames; public Person(String firstName, String[] middleNames, String lastName) { this.firstName = new SimpleStringProperty(firstName); this.middleNames = FXCollections.observableArrayList(middleNames); this.lastName = new SimpleStringProperty(lastName); } public String getFirstName() { return firstName.get(); } public StringProperty firstNameProperty() { return firstName; } public void setFirstName(String firstName) { this.firstName.set(firstName); } public ObservableList<String> getMiddleNames() { return middleNames; } public String getLastName() { return lastName.get(); } public StringProperty lastNameProperty() { return lastName; } public void setLastName(String lastName) { this.lastName.set(lastName); } } 

Alternative implementations

There may be other (perhaps more preferable ways) for this - for example, linking the bindings of elements in the code rather than FXML (this is what I usually do), or introducing a model using a dependency injection system. See afterburner.fx for an example of an injection approach - although I don’t know if the afterburner adds model objects to the FXML namespace or just injects it into the controller (if it does not inject into the FXML namespace, which can be a cool addition that you could request for him).

+5
source

Source: https://habr.com/ru/post/1215323/


All Articles