JavaFX: Run ChangeListener -
ho can run change method inside changelistener
in initialization. since run when changes happen. example have textfield
want set it's value 0 when it's empty, , this:
textfield.textproperty().addlistener(new changelistener<string>() { @override public void changed(observablevalue<? extends string> observable, string oldvalue, string newvalue) { if (!newvalue.matches("\\d*")) { textfield.settext(newvalue.replaceall("[^\\d]", "")); } if (newvalue.isempty()) textfield.settext("0"); } });
but @ start of application changed method not called. how work around issue?
there's no way access listener added property. keep reference it:
changelistener<string> textfieldlistener = (observable, oldvalue, newvalue) -> { if (!newvalue.matches("\\d*")) { textfield.settext(newvalue.replaceall("[^\\d]", "")); } if (newvalue.isempty()) textfield.settext("0"); }; textfield.textproperty().addlistener(textfieldlistener); textfieldlistener.changed(null, null, textfield.gettext());
or, perhaps more naturally, move actual functionality different method:
textfield.textproperty().addlistener((observable, oldvalue, newvalue) -> vetotextfieldchanges()); vetotextfieldchanges(); // ... private void vetotextfieldchanges() { string newtext = textfield.gettext(); if (!newtext.matches("\\d*")) { textfield.settext(newtext.replaceall("[^\\d]", "")); } if (newtext.isempty()) textfield.settext("0"); }
note whole approach of watching changes , modifying them if inconsistent business logic not satisfactory. example, if have other listeners registered property, may see intermediate (invalid) values of text. supported way use textformatter
. textformatter
both allows veto changes requested text, before textproperty()
updated, , convert text appropriate value. in case do:
unaryoperator<textformatter.change> filter = change -> { // remove non-digit characters inserted text: if (! change.gettext().matches("\\d*")) { change.settext(change.gettext().replaceall("[^\\d]", "")); } // if new text empty, replace text "0": if (change.getcontrolnewtext().isempty()) { change.setrange(0, change.getcontroltext().length()); change.settext("0"); } return change ; }; textformatter<integer> formatter = new textformatter<integer>(new integerstringconverter(), 0, filter); textfield.settextformatter(formatter);
now can use formatter (numeric) values directly via formatter's value
property, , bind them model, etc:
// assume model data model , valueproperty() returns property<integer>: formatter.valueproperty().bindbidirectional(model.valueproperty());
note binding both update formatter (and consequently text field) when model changes, , initialize depending on model value (thus providing solution original question).
Comments
Post a Comment