This discussion is archived
1 Reply Latest reply: Nov 5, 2012 8:23 AM by James_D RSS

bidirectional bind

959924 Newbie
Currently Being Moderated

how can I bind a detail pane with a selected row in a tableview in both ways?
Means when I select a row in the tableview the detail fields will updated, also when I Change the value in a detail field the value in the table have to Change.


  • 1. Re: bidirectional bind
    James_D Guru
    Currently Being Moderated
    I think you have to use a listener on your selected item property to achieve this (though others may see a more elegant way to do it).

    When I use "editor panels" I like to use separate fxml files and controllers for them, and you can still do this; define a property for your details pane and bind it to the selected item property in the table's selection model. Then register a change listener with the property, and update the bindings in the detail editor's controls to bind bidirectionally to the properties in the selected item.

    Example: first the standard Person class, which all table examples are required to use.
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    public class Person {
        private final SimpleIntegerProperty num;
        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        public Person(int id, String fName, String lName) {
          this.firstName = new SimpleStringProperty(fName);
          this.lastName = new SimpleStringProperty(lName);
          this.num = new SimpleIntegerProperty(id);
        public StringProperty firstNameProperty() {
          return firstName ;
        public String getFirstName() {
          return firstName.get();
        public void setFirstName(String fName) {
        public StringProperty lastNameProperty() {
          return lastName ;
        public String getLastName() {
          return lastName.get();
        public void setLastName(String fName) {
        public int getId() {
          return num.get();
        public void setId(int id) {
    FXML file for the details pane, which has text fields for first and last name:

    <?xml version="1.0" encoding="UTF-8"?>
    <?import javafx.scene.layout.GridPane?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.control.Label?>
    <GridPane xmlns:fx="" fx:controller="DetailsPaneController">
         <Label text="First Name">
         <Label text="Last Name">
         <TextField fx:id="firstNameTextField">
         <TextField fx:id="lastNameTextField">
    Controller for the Details pane: this defines the property for the person being edited, registers a change listener with it, and binds the text fields to the appropriate properties in the Person.
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.fxml.FXML;
    import javafx.scene.control.TextField;
    public class DetailsPaneController {
      private @FXML TextField firstNameTextField ;
      private @FXML TextField lastNameTextField ;
      private ObjectProperty<Person> personProperty ;
      public void initialize() {
        personProperty = new SimpleObjectProperty<Person>(null) ;
        personProperty.addListener(new ChangeListener<Person>() {
          public void changed(ObservableValue<? extends Person> observable,
              Person oldValue, Person newValue) {
            if (oldValue != null) {
            if (newValue != null) {
      public ObjectProperty<Person> personProperty() {
        return personProperty ;
      public Person getPerson() {
        return personProperty.get();
      public void setPerson(Person p) {
    Main FXML file. Just defines a table view and references the FXML file above.

    <?xml version="1.0" encoding="UTF-8"?>
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.control.TableView?>
    <HBox xmlns:fx="" fx:controller="TableWithDetailsController">
              <TableView fx:id="tableView"/>
              <fx:include source="DetailsPane.fxml" fx:id="detailsPane" />
    And the controller for the main fxml file. The initialize method initializes the table, and binds the selectedItem property to the person property defined in the details pane's controller:
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.fxml.FXML;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.scene.control.cell.PropertyValueFactory;
    public class TableWithDetailsController {
      private @FXML TableView<Person> tableView ;
      private @FXML DetailsPaneController detailsPaneController ;
      public void initialize() {
        final ObservableList<Person> data = FXCollections.observableArrayList(
            new Person(1, "Joe", "Pesci"),
            new Person(2, "Audrey", "Hepburn"),
            new Person(3, "Gregory", "Peck"),
            new Person(4, "Cary", "Grant"),
            new Person(5, "Robert", "De Niro")
        TableColumn<Person, Integer> idColumn = new TableColumn<Person, Integer>();
        idColumn.setCellValueFactory(new PropertyValueFactory<Person, Integer>("id"));
        TableColumn<Person, String> firstNameColumn = new TableColumn<Person, String>();
        firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
        TableColumn<Person, String> lastNameColumn = new TableColumn<Person, String>();
        lastNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
        tableView.getColumns().addAll(idColumn, firstNameColumn, lastNameColumn);
        detailsPaneController.personProperty().bind( tableView.getSelectionModel().selectedItemProperty() );
    Finally, for completeness, the application startup code:
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    public class TableWithDetails extends Application {
      public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("TableWithDetails.fxml"));
        Scene scene = new Scene(root);
      public static void main(String[] args) {


  • Correct Answers - 10 points
  • Helpful Answers - 5 points