Recent changes Random page
GAMING
Technology
 
Gaming
Entertainment
Science Fiction
Biggest wikis
Hobbies
Music
See more...

Binding to a POJO

From Planet JFX

Jump to: navigation, search
 

Contents

[edit] Introduction

At this time, JavaFX variables bound to a pure-Java object (POJO) will not automatically update as they should. This article describes one or more ways to get two-way binding working.

[edit] Problem Statement

Original Thread

I want to get a JFX button to change state given a property
change in Java code. I can pass the new state into the script
but the binding does not work.

[edit] Solution using a PropertyChangeListener

There is a lot of code involved in solving this problem. Let's use PropertyChangeEvents since they map pretty well to what we need to get the interaction working.

[edit] Java

package test;

// import statements
...

public class NameKeeper {
    // instance variables:
    private String nameVar;

    // property change listener methods:
    // note: you can delegate the implementations
    //  of these methods to a PropertyChangeSupport...
    public void addPropertyChangeListener(PropertyChangeListener list) ...
    public void removePropertyChangeListener(PropertyChangeListener list) ...
    private void fireEvent(PropertyChangeEvent e) ...

    // property methods:
    public String getName() ...
    public void setName(String name) {
        fireEvent(new PropertyChangeEvent(this, "name", nameVar, name));
        nameVar = name;
    }
}

[edit] JavaFX

import test.NameKeeper as JavaNameKeeper; 
// above can't be the same name as a JFX class.
import java.beans.*;

class NameKeeper {
    attribute name:String;
    private attribute backer:JavaNameKeeper;
    private attribute listener:PropertyChangeListener;
    private attribute suppressCascade:Boolean;
}

// we want just one listener created, no matter how many different backers we use:
trigger on new NameKeeper {
    var self = this;
    this.listener = new PropertyChangeListener {
        operation property Change(evt:PropertyChangeEvent) {
            var propertyName = evt.getPropertyName();
            println("NK.fx: got vetoChange: model:{self.backer} chg: '{propertyName}' from '{evt.getOldValue().toString()}' to 'evt.getNewValue().toString()}'");
            if (propertyName == "name") {
	        self.suppressCascade = true;
                self.name = (String)evt.getNewValue();
	        self.suppressCascade = false;
            } // endif
        } // endop
    };
}

trigger on NameKeeper.name = newValue {
    // only update backer if we are not updating in response to backer already...
    if (not suppressCascade) {
        backer.setName(newValue);
    } // endif
}

trigger on NameKeeper.backer[oldValue] = newValue {
    println("NK.fx: Setting model from '{oldValue}' to '{newValue}'");
    // remove change listener from old:
    if (oldValue <> null) {
        oldValue.removePropertyChangeListener(listener);
    } // end if

    // check new for null:    
    if (newValue <> null) {
        // we have a model, add change listener to new, rebuild:
        newValue.addPropertyChangeListener(listener);
        // capture the backer's name:
        name = backer.getName();

    } else {
        // no backing object, clear out:
        name = null;
    } // end if
}

Rate this article:
Share this article: