0

I have an array of wrapper objects which wrap javafx controls:

  • CheckBox
  • Spinner

I want to be able to listen to changes on the CheckBox or the Spinner. I have tried extracting the information I need but the problem with this is that it only works if the array has Spinner only.

Some of my code:

ObservableList<WrapperClass>  WrapperObjectList = FXCollections.observableArrayList(
     new Callback<WrapperClass, Observable[]>() {
          @Override
          public Observable[] call(WrapperClass param) {
               return new Observable[] {
                    ((Spinner) param.getControl()).valueProperty()
                };
          }
     }
);

WrapperClass.java

private Item item;
private Control control;

public WrapperClass(Item item, Control control) {
    this.item = item;
    this.control = control;
}
2
  • What's a NumberField? Can't you just do an instanceof check in the call() method? Commented Mar 31, 2017 at 15:58
  • @James_D that was an extension of Spinner. I've changed accordingly. Commented Mar 31, 2017 at 16:01

1 Answer 1

2

A fairly naive but straightforward solution would just be to test the type of the wrapped node:

ObservableList<WrapperClass>  WrapperObjectList = FXCollections.observableArrayList(
     new Callback<WrapperClass, Observable[]>() {
          @Override
          public Observable[] call(WrapperClass param) {
               if (param.getControl() instanceof Spinner) {
                   return new Observable[] {
                       ((Spinner) param.getControl()).valueProperty()
                   };
               } else if (param.getControl() instanceof CheckBox) {
                   return new Observable[] {
                       ((CheckBox) param.getControl()).selectedProperty()
                   };
               } else return new Observable[0] ;
          }
     }
);

A more elegant approach would be to expose the appropriate property from the WrapperClass. You could make WrapperClass abstract:

public abstract class WrapperClass {

    private Item item;
    private Control control;

    public WrapperClass(Item item, Control control) {
        this.item = item;
        this.control = control;
    }

    public abstract Observable observableValue() ;

}

and then create concrete subclasses:

public class SpinnerWrapper extends WrapperClass {

    private final Spinner spinner ;

    public SpinnerWrapper(Item item, Spinner spinner) {
        super(item, spinner);
        this.spinner = spinner ;
    }

    @Override
    public Observable observableValue() {
        return spinner.valueProperty();
    }
}

and similarly for CheckBoxSpinner. Then you just need

ObservableList<WrapperClass>  WrapperObjectList = FXCollections.observableArrayList(
     new Callback<WrapperClass, Observable[]>() {
          @Override
          public Observable[] call(WrapperClass param) {
               return new Observable[] {
                    param.observableValue()
                };
          }
     }
);

Alternatively, you could make WrapperClass generic and supply a function to it that returns the property you need:

public class WrapperClass<C extends Control> {

    private Item item ;
    private C control ;

    private Function<C, Observable> valueFunction ;

    public WrapperClass(Item item, C control, Function<C, Observable> valueFunction) { 
        this.item = item ;
        this.control = control ;
        this.valueFunction = valueFunction ;
    }

    public Observable observableValue() {
        return valueFunction.apply(control);
    }
}

which you would instantiate as

WrapperClass<Spinner> spinnerWrapper = new WrapperClass(someItem, someSpinner, 
    Spinner::valueProperty);
WrapperClass<CheckBox> checkBoxWrapper = new WrapperClass(someOtherItem, someCheckBox, 
    CheckBox::selectedProperty);

The observable list would be created with the extractor just returning param.observableValue() as above.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.