简体   繁体   中英

Is it possible to bind a TextProperty to an ObjectProperty's String attribute if it is not a String property?

How can I bind ObjectProperty 's attribute (that itself is not a property) to some other property like a TextField 's text property without using a ChangeListener ?

More specifically:

I would like to make a TextField change an ObjectProperty 's attribute.

Sample code:

MapDTO:

public class MapDTO {
    private String cityName;

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }
}

MapsManager:

public class MapsManager {

    private static ObjectProperty<MapDTO> map = new SimpleObjectProperty<>();

    public static MapDTO getMap() {
        return map.get();
    }

    public static ObjectProperty<MapDTO> mapProperty() {
        return map;
    }

    public static void setMap(MapDTO map) {
        MapsManager.map.set(map);
    }
}

BindingTestController :

public class BindingTestController {

    private TextField cityNameTF = new TextField();

    private void initialize() {

        // Bind the cityName label to the selected MapsManager mapProperty's cityName   
        cityNameTF.textProperty().bind(Bindings.createStringBinding(
            () -> MapsManager.mapProperty().getValue() == null ? null :
                MapsManager.mapProperty().getValue().getCityName(),
            MapsManager.mapProperty()));
    }
}

I have tried:

Creating a string property from the selected value String attribute but it did not pan out & I wasn't able to find the right way.

cityNameTF.textProperty().bindBidirectional(Bindings.createStringBinding(
() -> selectMapCB.getValue() == null ? null : selectMapCB.getValue().getCityName(), 
selectMapCB.valueProperty()));

Creating a string property from the mapProperty's String attribute.

cityNameTF.textProperty().bindBidirectional(Bindings.createStringBinding(
() -> MapsManager.getMapProperty().getValue() == null ? null : MapsManager.mapProperty().getValue().getCityName(),
MapsManager.mapProperty()));

Both options give the same error:

bindBidirectional (javafx.beans.property.Property<java.lang.String>)
in StringProperty cannot be applied to (javafx.beans.binding.StringBinding)

In both cases replacing bindBidirectional with bind works but then I can't change the text in the TextField . I realized this is because I am binding the TextField 's text to the cityName 's String. So I thought of binding it one way but in the opposite direction, something like:

MapsManager.mapProperty().????.bind(cityNameTF.textProperty());

But "????" - I don't have a property for the String and I don't know how to create a StringBinding or StringProperty on the fly if that's even possible.

Your MapDTO is basically a JavaBean - a class with a field and its getter and setter. We'll call such a field a bean property . Since you can't bind to or from these properties, JavaFX provides adapters that bridge them to JavaFX properties. They are located in the package javafx.beans.property.adapter :

Provides various classes that act as adapters between a regular Java Bean property and a corresponding JavaFX Property.

Internally, they function as wrappers of the bean property.

Since your MapDTO contains a String we'll use a JavaBeanStringProperty . Note that:

As a minimum, the Java Bean class must implement a getter and a setter for the property. The class, as well as the getter and a setter methods, must be declared public.

so we obey the requirements.

We create these adapter with their builders, JavaBeanStringPropertyBuilder in this case:

JavaBeanStringProperty cityNameProperty = JavaBeanStringPropertyBuilder.create()
                                              .bean(MapsManager.getMap())
                                              .name("cityName")
                                              .build();

The builders access the data reflectively. Now we can use the created property as usual:

cityNameProperty.bind(cityNameTF.textProperty());

and changes to the text field's text property will change cityName in the MapDTO instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM