java - Bind two Spinner controls into a TableView in JavaFX -


how bind 2 spinner controls tableview ? according sreenshot below, : cola = colb / 2 (and colb = cola x 2...) :

exemple screenshot

here snippet (deliberately simple) used expose problem :

testapp.java

public class testapp extends application {      @override     public void start(stage stage) throws exception {          final tableview<mybean> tableview = new tableview<>();         final tablecolumn<mybean, integer> cola = new tablecolumn<>("col a");         final tablecolumn<mybean, integer> colb = new tablecolumn<>("col b");          cola.setcellfactory(col -> new spinnercell<mybean, integer>());         cola.setcellvaluefactory(new propertyvaluefactory<mybean, integer>("vala"));          colb.setcellfactory(col -> new spinnercell<mybean, integer>());         colb.setcellvaluefactory(new propertyvaluefactory<mybean, integer>("valb"));          tableview.setcolumnresizepolicy(tableview.constrained_resize_policy);         tableview.setitems(fxcollections.observablearraylist(new mybean(1, 2)));         tableview.getcolumns().addall(cola, colb);          stage.setscene(new scene(new vbox(tableview), 500, 300));         stage.show();     }      public static void main(string[] args) {         application.launch();     } } 

spinnercell.java

public class spinnercell<s, t> extends tablecell<s, t> {      private spinner<integer> spinner;     private observablevalue<t> ov;      public spinnercell() {         this.spinner = new spinner<integer>(0, 100, 1);         setalignment(pos.center);     }      @override     protected void updateitem(integer item, boolean empty) {         super.updateitem(item, empty);          if (empty) {             settext(null);             setgraphic(null);         } else {             settext(null);             setgraphic(this.spinner);              if(this.ov instanceof integerproperty) {                 this.spinner.getvaluefactory().valueproperty().unbindbidirectional(((integerproperty) this.ov).asobject());             }              this.ov = gettablecolumn().getcellobservablevalue(getindex());              if(this.ov instanceof integerproperty) {                 this.spinner.getvaluefactory().valueproperty().bindbidirectional(((integerproperty) this.ov).asobject());             }         }     } } 

mybean.java

public class mybean {      private integerproperty vala, valb;      public mybean(int vala, int valb) {         this.vala = new simpleintegerproperty(this, "vala", vala);         this.valb = new simpleintegerproperty(this, "valb", valb);     }      public integerproperty valaproperty() {         return this.vala;     }      public void setvala(int vala) {         this.vala.set(vala);     }      public int getvala() {         return vala.get();     }      public integerproperty valbproperty() {         return this.valb;     }      public void setvalb(int valb) {         this.valb.set(valb);     }      public int getvalb() {         return valb.get();     } } 

here's example of using extended bidirectional binding support in mybean:

public static class mybean {      private integerproperty vala;      private integerproperty valb;      public mybean(int vala) {         this.vala = new simpleintegerproperty(this, "vala", vala);         this.valb = new simpleintegerproperty(this, "valb", 0);         updateb(this.vala, null, this.vala.get());         bidirectionalbinding.<number, number>bindbidirectional(                 this.vala, this.valb, this::updateb, this::updatea);     }      protected void updateb(observablevalue<? extends number> source,  number old, number value) {         setvalb(value.intvalue() * 2);     }      protected void updatea(observablevalue<? extends number> source, number old, number value) {         setvala(value.intvalue() / 2);     }      ... // same in op's code } 

plus in spinnercell, bind bean property directly (vs. asobject wrapper) - there's typing issue don't understand entirely [update, see below] (me , generics never become friends ;-) stands in way of successful bidi-binding:

public static class spinnercell<s, t extends number> extends tablecell<s, t> {      private spinner<t> spinner;     private observablevalue<t> ov;      public spinnercell() {         this(1);     }          public spinnercell(int step) {         this.spinner = new spinner<>(0, 100, step);         setalignment(pos.center);     }      @override     protected void updateitem(t item, boolean empty) {         super.updateitem(item, empty);          if (empty) {             settext(null);             setgraphic(null);         } else {             settext(null);             setgraphic(this.spinner);              if(this.ov instanceof property) {                 this.spinner.getvaluefactory().valueproperty().unbindbidirectional(((property) this.ov));             }              this.ov = gettablecolumn().getcellobservablevalue(getindex());              if(this.ov instanceof property) {                 this.spinner.getvaluefactory().valueproperty().bindbidirectional(((property) this.ov));             }         }     } } 

update (in understanding problem .asobject)

the problem not typing such, (struck again!) weak listener registration in bidi-binding:

// spinner type spinner<integer> spinner; // value type (in valuefactory): objectproperty<integer> valueproperty; // value type in bean: integerproperty valxproperty; // bindeable spinner's value, needs wrapped // objectproperty<integer> // intuitively ... wrong! valueproperty.bindbidirectional(bean.valxproperty().asobject()); 

the wrapper created on fly local reference can (and is) garbage collected containing method left ... these weak listening contexts, none (? @ least none i'm aware of) of alternatives satisfying:

  • relax on typing of spinner: using number (vs.integer) doesn't require wrapper because interproperty instanceof objectproperty<number>
  • keep strong reference wrapper somewhere

Comments

Popular posts from this blog

c++ - No viable overloaded operator for references a map -

java - Custom OutputStreamAppender not run: LOGBACK: No context given for <MYAPPENDER> -

java - Cannot secure connection using TLS -