8 Replies Latest reply: Apr 8, 2013 10:50 AM by 1001443 RSS

    Slider Listener

    1001443
      I have 8 slider controls in an HBox and I want to add a listener to each one that will somehow let me know which slider it is. Each slider represents a channel for a device, and although I can add a listener that passes back a Number which represents the new value of the slider, it doesn't tell me which slider it is. Although I can add an int that represents the channel number of the slider to its user data, there doesn't seem to be a way of extracting it from the type returned (Number). The code looks like this:

      HBox hbox = new HBox(8); // spacing
      for(int i = 0; i < gain.length; i++) // for each output
      {
      gain[i] = SetLook(new Slider(0,100,0));
      gain.setUserData(i+1); // the input number
      hbox.getChildren().add(gain[i]);
      gain[i].valueProperty().addListener(new ChangeListener<Number>()
      {
      @Override
      public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue)
      {
      // makeGainChange((int)newValue.getUserData(),newValue.intValue());
      makeGainChange(1, newValue.intValue());
      }
      });
      }
        • 1. Re: Slider Listener
          James_D
          HBox hbox = new HBox(8); // spacing
          for(int i = 0; i < gain.length; i++) // for each output
          {
            gain = SetLook(new Slider(0,100,0));
            // gain.setUserData(i+1); // the input number
            hbox.getChildren().add(gain);
          
            // Add this:
            final int inputNumber = i+1 ;
           
            gain.valueProperty().addListener(new ChangeListener<Number>()
            {
              @Override
              public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue)
              {
                // now pass the input number to your method:
                makeGainChange(inputNumber, newValue.intValue());
              }
            });
          }
          Edited by: James_D on Apr 7, 2013 12:16 PM
          • 2. Re: Slider Listener
            shakir.gusaroff
            Hi. I would do it like this:
             final SimpleIntegerProperty  userD = new SimpleIntegerProperty(0);
                    HBox hbox = new HBox(8); // spacing
                    for (int i = 0; i < gain.length; i++) // for each output
                    {
                        gain = SetLook(new Slider(0, 100, 0));
                        userD.set(i + 1);
                   //     gain.setUserData(i + 1); // the input number
                        hbox.getChildren().add(gain);
                        gain.valueProperty().addListener(new ChangeListener<Number>() {
                            @Override
                            public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue) {
                               makeGainChange(userD.get(),newValue.intValue());
                               // makeGainChange(1, newValue.intValue());
                            }
                        });
                    }
            • 3. Re: Slider Listener
              James_D
              shakir.gusaroff wrote:
              Hi. I would do it like this:
              That doesn't actually work.
              import javafx.application.Application;
              import javafx.beans.property.SimpleIntegerProperty;
              import javafx.beans.value.ChangeListener;
              import javafx.beans.value.ObservableValue;
              import javafx.geometry.Orientation;
              import javafx.scene.Scene;
              import javafx.scene.control.Slider;
              import javafx.scene.layout.HBox;
              import javafx.stage.Stage;
              
              public class SliderListenerTest extends Application {
              
                @Override
                public void start(Stage primaryStage) {
                  final SimpleIntegerProperty userD = new SimpleIntegerProperty(0);
                  final Slider[] gain = new Slider[8];
                  HBox hbox = new HBox(8); // spacing
                  for (int i = 0; i < gain.length; i++) // for each output
                  {
                    gain[i] = setLook(new Slider(0, 100, 0));
                    userD.set(i + 1);
                    // gain.setUserData(i + 1); // the input number
                    hbox.getChildren().add(gain);
              gain[i].valueProperty().addListener(new ChangeListener<Number>() {
              @Override
              public void changed(ObservableValue<? extends Number> ov,
              Number oldValue, Number newValue) {
              makeGainChange(userD.get(), newValue.intValue());
              // makeGainChange(1, newValue.intValue());
              }
              });
              }
              primaryStage.setScene(new Scene(hbox, 600, 600));
              primaryStage.show();
              }

              private void makeGainChange(int inputNumber, int value) {
              System.out.printf("Input %d changed to %d%n", inputNumber, value);
              }

              private Slider setLook(Slider slider) {
              slider.setOrientation(Orientation.VERTICAL);
              return slider;
              }

              public static void main(String[] args) {
              launch(args);
              }
              }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
              • 4. Re: Slider Listener
                shakir.gusaroff
                Thank you John for pointing that out.
                The userD property should be inside the loop:
                for (int i = 0; i < gain.length; i++) // for each output
                    {
                     final SimpleIntegerProperty userD = new SimpleIntegerProperty(0);
                      gain[i] = setLook(new Slider(0, 100, 0));
                The question was how to set the user data and retrieve later these data.
                User data can be set on the node. He is trying to get the user data from Number, which is illegal.
                I would prefer SimpleIntegerProperty as user data instead of int because you do not need to cast.
                • 5. Re: Slider Listener
                  James_D
                  You can use the cast with a Number; it would just require the correct cast. For example
                  gain.setUserData(i+1);
                  ...
                  makeGainChange(((Number)newValue.getUserData()).intValue(),newValue.intValue());
                  But why add that (admittedly small) overhead, and use up the userData slot, when you can solve the problem with a local variable?
                  • 6. Re: Slider Listener
                    1001443
                    James,

                    I tried your example to get the user data, but the compiler complains with:
                    "The method getUserData() is undefined for the type Number"

                    This emphasizes my lack of understanding about the mechanisms behind how the object is passed to the 'changed' method, and how the variable 'gainNumber' is unique for each call to the 'changed' method. Is this particular feature unique to JavaFX or part of the feature set introduced since Java 1.4?
                    • 7. Re: Slider Listener
                      James_D
                      Oh, yeah, sorry; you need to call getUserData() on the Slider, not on the value if you want to use that mechanism.

                      The control is not directly passed to the changed(...) method. You're listening for changes to an ObservableValue - in this case it's the valueProperty of the slider which is a DoubleProperty - and a reference to that ObservableValue is passed to the changed(...) method. You could get the slider from the ObservableValue parameter to the changed(...) method, but it's not very clean: cast the observableValue to a Property<Number>, call getBean() on the property, and cast the result of that to a Node. Then call getUserData() on the Node. But like I said, I wouldn't do it like that anyway. The point is you already have a reference to the slider, or any other data you need. Just arrange for that data to be available to your listener.

                      In the solution
                      for(int i = 0; i < gain.length; i++) // for each output
                      {
                        gain[i] = SetLook(new Slider(0,100,0));
                        // gain.setUserData(i+1); // the input number
                        hbox.getChildren().add(gain);
                       
                        // Add this:
                        final int inputNumber = i+1 ;
                       
                        gain.valueProperty().addListener(new ChangeListener<Number>()
                      {
                      @Override
                      public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue)
                      {
                      // now pass the input number to your method:
                      makeGainChange(inputNumber, newValue.intValue());
                      }
                      });
                      }
                      each time you go through the loop, i holds the current loop index. You assign i+1 to a final variable inputNumber (declared for each iteration, so there is effectively a new final variable for each iteration of the loop). The anonymous inner class assigned as the listener to your value property (again, one listener each time you iterate through the loop) captures the final variable value. The way this works (as I understand it) is that the compiler effectively creates a class whose constructor takes a parameter corresponding to the final variable that is captured. There's nothing specific to JavaFX here (there's no specific JavaFX syntax, it's all standard Java code) and nothing "new" to Java 1.5.0; anonymous inner classes were introduced in Java 1.1 and have always been able to capture local final variables.
                      
                      If you need access to the control, you can do the same trick:
                      for(int i = 0; i < gain.length; i++) // for each output
                      {
                      final Slider slider = new Slider(0, 100, 0);
                      gain[i] = SetLook(slider); // I'm assuming SetLook(slider) configures the slider and returns a reference to it?
                      hbox.getChildren().add(gain);

                      // Add this:
                      final int inputNumber = i+1 ;

                      gain[i].valueProperty().addListener(new ChangeListener<Number>()
                      {
                      @Override
                      public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue)
                      {
                      // You can access the control 'slider' if you need to...
                      // now pass the input number to your method:
                      makeGainChange(inputNumber, newValue.intValue());
                      }
                      });
                      }
                      If you prefer named classes, the equivalent would look something like this. I prefer anonymous classes but this might make what's happening clearer to you:
                      for(int i = 0; i < gain.length; i++) // for each output
                      {
                      gain[i] = SetLook(new Slider(0,100,0));
                      hbox.getChildren().add(gain);

                      gain[i].valueProperty().addListener(new GainValueListener(i+1));

                      }
                      // ....

                      // Inner class (inside the same class as the code above)
                      private class GainValueListener implements ChangeListener<Number> {
                      private final int gainNumber ;
                      GainValueListener(int number) {
                      this.gainNumber = number ;
                      }
                      @Override
                      public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue) {
                      makeGainChange(gainNumber, newValue.intValue());
                      }
                      }
                      Edited by: James_D on Apr 8, 2013 8:16 AM                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
                      • 8. Re: Slider Listener
                        1001443
                        James,

                        Thank you very much for clearing up my confusion with regards to final variables and anonymous inner classes. Your example replacing the anonymous inner class with an actual inner class was priceless. With regards to the gain variable, here's the actual code section:
                            HBox hbox = new HBox(8); // spacing
                            for(int i = 0; i < gain.length; i++) // for each output
                            {
                              gain[i] = SetLook(new Slider(0,100,0));
                              hbox.getChildren().add(gain);
                        final int gainNumber = i+1;
                        gain[i].valueProperty().addListener(new ChangeListener<Number>()
                        {
                        @Override
                        public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue)
                        { makeGainChange(gainNumber, newValue.intValue());}
                        });
                        }
                        ...
                        }

                        private Slider SetLook (Slider t)
                        {
                        t.setOrientation(Orientation.VERTICAL);
                        t.setShowTickMarks(true);
                        t.setShowTickLabels(true);
                        t.setMajorTickUnit(10);
                        t.setBlockIncrement(2);
                        return t;
                        }
                        I'm using a gain array because I'll be implementing an IP server thread in order to allow clients to set the gain for each input. The array will make it easier to control the sliders in this case. Think of the UI here as a front panel to the device as well as a secondary means of controlling it. This application is a going to be a teaching aid where developing the client side (on a control system) using a touch panel is the real goal. This is merely a simulator of an IP controllable audio switcher.
                        
                        Edited by: LCubed on Apr 8, 2013 8:46 AM
                        
                        Edited by: LCubed on Apr 8, 2013 8:47 AM
                        
                        Edited by: LCubed on Apr 8, 2013 8:49 AM