JEP Proposal: Fluent Bindings for multiple observables
John Hendrikx
john.hendrikx at gmail.com
Tue Oct 28 08:06:23 UTC 2025
You are right, I did use an even older style, guess that shows how
rarely I even look at the `Bindings` class these days as almost
everything can be done fluently now.
The JEP I propose is specifically to fill a gap in the fluent bindings,
but that doesn't mean this is currently impossible to achieve. It is
similar to how `map` basically can replace 50% of the methods in
`Bindings` and how `flatMap` replaces all the `select` methods.
The reason I'm proposing it is to make fluent bindings possible with
more than one source. I mean, I can do this:
Property<Point2D> point = ...;
label.textProperty().bind(point.map(p -> "x: " + p.getX() + ", y: "
+ p.getY()));
But when the things I need are stored in multiple properties, `map`
becomes useless:
IntegerProperty xpos = ... ;
IntegerProperty ypos = ... ;
// can't use `map` on `xpos` or `ypos` as it would only react if
one of these properties change
In the proposal, it would become possible to observe and react to
multiple sources:
xpos.with(ypos).map((x, y) -> "x: " + x + ", y: " + y);
I've limited the proposal to two sources as this is sufficient to scale
to an arbitrary number, albeit with additional mapping steps. It is
however open ended and can be extended to more than 2 sources easily
(which is something open for discussion or possible as an extension
later). In other words, by adding another helper interface we can also
have:
xpos.with(ypos, zpos).map((x, y, z) -> ... );
In its most basic form however, two sources will also work:
xpos.with(ypos).map(Point2D::new).with(zpos).map((p, z) -> ... );
I think supporting two sources will cover 80% of the cases without
requiring additional mapping steps, and that quickly approaches 100%
when you potentially allow for 3 or 4 sources.
--John
On 27/10/2025 20:48, Andy Goryachev wrote:
> Doesn't
>
> DoubleBinding createDoubleBinding(final Callable<Double> func,
> final Observable... dependencies)
>
> handles the use case you describe?
>
> -andy
>
> *From: *openjfx-dev <openjfx-dev-retn at openjdk.org> on behalf of John
> Hendrikx <john.hendrikx at gmail.com>
> *Date: *Sunday, October 26, 2025 at 02:59
> *To: *openjfx-dev <openjfx-dev at openjdk.org>
> *Subject: *JEP Proposal: Fluent Bindings for multiple observables
>
> JEP: https://gist.github.com/hjohn/611acb65769b68a845b8919c62a3e99a
>
> Hi everyone,
>
> I'd like to propose an extension to the fluent bindings API on
> ObservableValue (map, flatMap, orElse) which were introduced in JavaFX
> 19 over 3 years ago.
>
> The API currently is very powerful when dealing with a single
> observable, but lacks support when dealing with multiple observables.
> For example, let's say you want to compute a width/height ratio. You
> could write this:
>
> ObservableValue<Double> ratio = width.map(w -> w / height.get());
>
> ... but you'll quickly find that such an observable will not update
> itself when height changes, only when width changes.
>
> The go-to solution for this is currently:
>
> DoubleBinding ratio = new DoubleBinding() {
> { bind(width, height); }
>
> protected double computeValue() { return width.get() /
> height.get(); }
> }
>
> My proposal would extend ObservableValue with a new `with` method that
> returns an intermediate stage that can be easily converted back to an
> ObservableValue:
>
> ObservableValue<Double> ratio = width.with(height).map((w, h) -> w /
> h); // yields a ratio that updates whenever w or h changes
>
> Or for example:
>
> ObservableValue<Point> point = x.with(y).map(Point::new); //
> yields a Point that updates whenever x or y changes
>
> The intermediate stage would not be an observable value itself. This
> limits the API surface, and makes this proposal fairly lightweight and
> much easier to implement.
>
> Please see the JEP for the full proposal. I look forward to your
> feedback!
>
> --John
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20251028/ba06ed42/attachment-0001.htm>
More information about the openjfx-dev
mailing list