1

I recently wrote function like this in my JavaFX application:

public static <T1, T2> void bindAndSet(ReadOnlyProperty<T1> sourceProperty, Property<T2> targetProperty, Function<T1, T2> converter) {
    sourceProperty.addListener(new WeakChangeListener<>((obs, oldVal, newVal) -> targetProperty.setValue(converter.apply(newVal))));
    targetProperty.setValue(converter.apply(sourceProperty.getValue()));
}

This is unidirectional bind with transformation and setting initial value. I have small experience in JavaFX but it seems like it should be quite common part of an application that uses binding. Property#bind seems nearly useless. It does not allow converting types and from checking source code it does not set initial value.

Is there a method (or 2) that provide such functionality? Or maybe I am using JavaFX API in a wrong way?

Sankozi
  • 500
  • 5
  • 22
  • 1
    what about extending ObjectBinding and applying converter in computeValue()? – Sergey Grinev Sep 14 '21 at 12:53
  • @SergeyGrinev I am not 100% sure how it would look, but it seems it would be larger than my solution, although analyzing this I have found `Bindings` class that looks interesting but often not type safe – Sankozi Sep 14 '21 at 13:31
  • 1
    What's the problem, exactly? BTW: wouldn't the weakListener be gc'ed almost immediately? Also: _ it does not set initial value_ - why should it? after the binding, its value _is_ the sourceValue. Not entirely certain about notifications at the time of property.bind .. there's some work done on binding, see the openjfx mailinglist (and repo) – kleopatra Sep 14 '21 at 13:59
  • currently, the property notifies on binding - so really don't see the problem here. – kleopatra Sep 14 '21 at 15:57
  • @kleopatra In my case listener is in UI so as long as it is shown (or reachable) it will not be GC'ed, without setting initial value UI components do not look like they know about sourceValue you mentioned – Sankozi Sep 17 '21 at 09:51
  • @kleopatra also in case of bidirectional binding the initial value is set - https://stackoverflow.com/questions/41014304/javafx-initial-value-of-bidirectional-binding – Sankozi Sep 17 '21 at 10:04
  • _without setting initial value UI components do not look like they know about sourceValue_ might be a problem in your code or me not fully understanding your problem - no way to tell without a [mcve] ;) – kleopatra Sep 17 '21 at 12:11

1 Answers1

2

You can use Bindings.createObjectBinding():

targetProperty.bind(Bindings.createObjectBinding(
        () -> converter.apply(sourceProperty.get()), sourceProperty));
Oboe
  • 2,643
  • 2
  • 9
  • 17
  • Nice! It is smaller than my solution, the only drawback - it is more error prone (but the risk is small). It also supports more use cases. Thanks! – Sankozi Sep 17 '21 at 10:02
  • @Sankozi I agree, it's not perfect but it's short. Glad it helped ;) – Oboe Sep 17 '21 at 15:37