3 Replies Latest reply: Jul 4, 2013 10:23 AM by James_D RSS

    Strange behavior with Bindings??

    WhiteAntelope

      Hello to all JavaFX 2 Binding experts,

       

      I have a strange behavior with Bindings in JavaFX 2.2 (Java 1.7 update 21). Please have a look at the following source code:

       

      package test;
      
      
      import javafx.application.Application;
      import javafx.beans.binding.BooleanBinding;
      import javafx.beans.property.SimpleBooleanProperty;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.fxml.FXML;
      import javafx.fxml.FXMLLoader;
      import javafx.scene.Parent;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.control.RadioButton;
      import javafx.stage.Stage;
      
      
      public class BindingVsProperty extends Application
      {
          @FXML
          private RadioButton opt11;
      
      
          @FXML
          private RadioButton opt12;
      
      
          @FXML
          private RadioButton opt21;
      
      
          @FXML
          private RadioButton opt22;
      
      
          @FXML
          private Label lbl11And21;
      
      
        @Override
          public void start(Stage arg0) throws Exception
          {
              FXMLLoader l_loader = new FXMLLoader();
              l_loader.setLocation(BindingVsProperty.class.getResource("BindingVsproperty.fxml"));
              l_loader.setController(this);
              l_loader.load();
              Scene l_scene = new Scene((Parent)l_loader.getRoot());
              arg0.setScene(l_scene);
      
      
              useBinding1();
              //useBinding2();
              //useBinding3();
      
      
              arg0.show();
          }
      
      
          private void useBinding1() // NOT WORKING - ChangeListener.changed(..) is not called
          {
              BooleanBinding l_andOpt11Opt21 = opt11.selectedProperty().and(opt21.selectedProperty());
              l_andOpt11Opt21.addListener(new ChangeListener<Boolean>()
              {
                  @Override
                  public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2)
                  {
                      System.out.println("Opt 1.1 AND Opt 2.1 changed to: " + arg2);
                  }
              });
          }
      
      
          private void useBinding2() // OK - ChangeListener.changed(..) is called
          {
              BooleanBinding l_andOpt11Opt21 = opt11.selectedProperty().and(opt21.selectedProperty());
              lbl11And21.visibleProperty().bind(l_andOpt11Opt21);
              l_andOpt11Opt21.addListener(new ChangeListener<Boolean>()
              {
                  @Override
                  public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2)
                  {
                      System.out.println("Opt 1.1 AND Opt 2.1 changed to: " + arg2);
                  }
              });
          }
      
      
          private void useBinding3() // NOT WORKING - ChangeListener.changed(..) is not called
          {
              BooleanBinding l_andOpt11Opt21 = opt11.selectedProperty().and(opt21.selectedProperty());
              new SimpleBooleanProperty(false).bind(l_andOpt11Opt21);
              l_andOpt11Opt21.addListener(new ChangeListener<Boolean>()
              {
                  @Override
                  public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2)
                  {
                      System.out.println("Opt 1.1 AND Opt 2.1 changed to: " + arg2);
                  }
              });
          }
      
      
          public static void main(String[] args)
          {
              launch(args);
          }
      
      
      }
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      

       

      <?xml version="1.0" encoding="UTF-8"?>
      
      
      <?import java.lang.*?>
      <?import java.util.*?>
      <?import javafx.scene.control.*?>
      <?import javafx.scene.layout.*?>
      <?import javafx.scene.paint.*?>
      
      
      <BorderPane id="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="371.0" xmlns:fx="http://javafx.com/fxml">
        <center>
          <AnchorPane prefHeight="200.0" prefWidth="200.0">
            <children>
              <Label id="lblAnd" fx:id="lbl11And21" layoutX="82.0" layoutY="121.0" text="Group1 Opt1 AND Group2 Opt1 is true" textFill="#41cc00" visible="false" />
              <RadioButton fx:id="opt21" layoutX="216.0" layoutY="24.0" mnemonicParsing="false" text="Group 2 - Opt 1">
                <toggleGroup>
                  <ToggleGroup fx:id="group2" />
                </toggleGroup>
              </RadioButton>
              <RadioButton fx:id="opt22" layoutX="216.0" layoutY="67.0" mnemonicParsing="false" text="Group 2 - Opt 2" toggleGroup="$group2" />
              <RadioButton fx:id="opt11" layoutX="29.0" layoutY="24.0" mnemonicParsing="false" text="Group 1 - Opt 1">
                <toggleGroup>
                  <ToggleGroup fx:id="group1" />
                </toggleGroup>
              </RadioButton>
              <RadioButton fx:id="opt12" layoutX="29.0" layoutY="67.0" mnemonicParsing="false" text="Group 1- Opt 2" toggleGroup="$group1" />
            </children>
          </AnchorPane>
        </center>
      </BorderPane>
      
      
      
      
      
      

       

      What I need for my application is the use case in useBinding1(), i.e., a BooleanBinding where several listeners are attached to. The problem is that I never get a callback in the ChangeListener if one of the RadioButton.selectedProperty() is changed.

       

      Now I tried what happens if I use the same BooleanBinding for another binding to a property plus the listener, now the listener gets callbacks as expected! (see useBinding2() )

       

      Than I thought may be Bindings must be bound in order to trigger listeners and tried useBinding3() where I bind the BooleanBinding to a new BooleanProperty, in this case the listener doesn't get callback anymore...

       

      And now I'm very frustrated and hope that anyone out there can help me to understand this strange behavior.

      Thanks a lot!

       

      WhiteAntelope

        • 1. Re: Strange behavior with Bindings??
          James_D

          All these work just fine for me: the listeners are all called as expected. Note that the listener is only invoked when the value of the binding actually changes, which doesn't happen every time a radio button is pressed. (For example, if both buttons are unselected, the binding is false. If one button is selected, the binding remains false and the listener is not invoked. When the second button is selected, the binding becomes true, and the listener is invoked.)

          • 2. Re: Strange behavior with Bindings??
            WhiteAntelope

            It's clear that the listener is only invoked if the value of the Binding changes as you have described above. Which version of the JVM and JavaFX are you using? I've continued working on the problem but the only way to get listener callbacks for me is to bind any BooleanProperty of any Node (must be in the scene graph!) to the BooleanBinding additionally to the listener :-(

            Any more ideas out there?

            • 3. Re: Strange behavior with Bindings??
              James_D

              I'm using JDK 1.7.0_25 with the accompanying JavaFX (2.2.25). I tested it on 1.7.0_21 and 1.8.0 ea b96 and it worked on those too.