Thanks for the investigation! I've prepared a PR that fixes this issue: https://github.com/openjdk/jfx/pull/614
On Sat, Aug 28, 2021 at 11:02 PM John Hendrikx <hj...@xs4all.nl> wrote: > > This actually isn't an issue because adding an invalidation listener > revalidates the property as well (I'm not sure why, but I noticed this > before while working on fluent bindings). > > However, there is another issue. When I recreate a bidirectional with > two invalidation listeners with special logic to ignore my own > invalidation listener triggering again when the other property gets > updated. > > When you include this logic (using the "updating" field in the current > code) in combination with invalidation listeners, the field that was > just updated does NOT get revalidated. Any further changes to that > field will therefore not trigger an invalidation event and the > bidirectional nature of the binding breaks. > > Try this example: > > import javafx.application.Application; > import javafx.beans.InvalidationListener; > import javafx.beans.Observable; > import javafx.beans.property.SimpleDoubleProperty; > import javafx.stage.Stage; > > public class TestBug8264770 extends Application { > > public static void main(String[] args) { > Application.launch(args); > } > > static SimpleDoubleProperty p1 = new SimpleDoubleProperty(2); > static SimpleDoubleProperty p2 = new SimpleDoubleProperty(3); > > @Override > public void start(Stage stage) throws Exception { > InvalidationListener invalidationListener = obs -> invalidated(obs); > > p1.addListener(invalidationListener); > p2.addListener(invalidationListener); > > p1.setValue(4); > p2.setValue(5); > > // Prints p1 = 4.0 (!!) > System.out.println("Expect p1 to be 5, but was: " + p1.getValue()); > } > > private boolean updating = false; > > private void invalidated(Observable source) { > if (!updating) { > try { > updating = true; > > if(source == p1) { > System.out.println("Setting p2 to " + p1.get()); > p2.set(p1.get()); > } > else { > System.out.println("Setting p1 to " + p2.get()); > p1.set(p2.get()); > } > } > finally { > updating = false; > } > } > } > } > > --John >