Limit what values ​​will be reset in javafx property?

What is the best way to keep javafx property value within certain limits?

(Or is it a bad practice, existing for some reason, to never filter values ​​wrapped in javafx properties?)

Example1: Avoid Negative Values ​​in IntegerProperty
Example2: keeping IntegerProperty within a list

First idea: - override IntegerPropertyBase.set(int) . It is safe? In fact, setValue(int) only calls set(int) , but - if this implementation changes one day - control over the set values ​​is lost.

Second idea: - override IntegerPropertyBase.invalidate() . But at this point, the value has already been established.

Will it better match the javafx properties, throw an IllegalArgumentException (or an ArrayIndexOutOfBoundsException if the wrapped value is an array index) or is it better to discard the value outside the bounds by setting the last value within the bounds

Maybe so:

  class BoundedIntegerProperty extends IntegerPropertyBase { (...) int oldValue = defaultValueInBounds; boolean settingOldValue = false; public void invalidated() { if(!settingOldValue){ if(outOfBounds(get())){ settingOldValue = true; set(oldValue); } else { oldValue = get(); } } else settingOldValue = false; } } 

Only throwing an exception from invalidated () for values ​​outside the bounds can leave the value of the property out of bounds.

Am I missing anything in the javafx properties provided for filtering values?

(If necessary, please help me improve the possibly bad English of this text ...)

+6
source share
2 answers

In both examples, there seemed to be a logical default value (for example, if it should be positive, negative numbers turn into 0). Assuming you are documenting well (defaults if the value is invalid), I think your first approach seems to be on the right track.

I would recommend starting with a specific class, such as SimpleIntegerProperty , as the class you are extending (unless there are reasons why you chose IntegerPropertyBase ).

I would then overwrite both the set(int) method and the setValue(Number) method, wrapping the parent in your logic:

  /** * Explanation that values under 0 are set to 0 */ @Override public void set(int value){ super.set(value > 0 ? value : 0); } /** * Explanation that values under 0 are set to 0 */ @Override public void setValue(Number value){ super.setValue(value.intValue() > 0 ? value : 0); } 

There may be times when there are no booleans by default (or you just want to reject invalid values). In this case, it is a little more complicated - you really would like to use a method signature like this so that the caller knows if the value has changed:

 public boolean set(int value) 

To do this, you will need to return to several classes - right up to ReadOnlyIntegerProperty and implement the configuration / invalidation structure yourself.

I would not use Exceptions to handle invalid input. This is the legal use of exceptions, but I am afraid that the Exception will be used for verification. Exceptions are very resource intensive and should only be hit if there is something that needs to be fixed. So it’s really about your intentions and how much you trust people using your class to do the right thing (and check them before submitting).

+2
source

I suppose I understand that you are shooting better now. You want to perform user input validation.

When you check your user, there are two ways to approach him:

  • Confirm immediately after any changes and provide feedback
  • Confirm when focus leaves input area

You will use property listeners with both - it's just a matter of what kind of listeners you come across.

In the first case, you will directly listen to the property that you are checking:

  TextField field = new TextField(); field.textProperty().addListener(new ChangeListener<String>(){ @Override public void changed(ObservableValue<? extends String> value, String oldValue, String newValue) { //Do your validation or revert the value }}); 

In the second case, you listen to the focused property and check when the focus is lost (you can save the last checked value in this listener to help return the value if necessary):

  TextField field = new TextField(); field.focusedProperty().addListener(new ChangeListener<Boolean>(){ String lastValidatedValue = ""; @Override public void changed(ObservableValue<? extends Boolean> value, Boolean oldValue, Boolean newValue) { if(newValue == false && oldValue == true){ //Do your validation and set `lastValidatedValue` if valid } }}); 

Note: I assumed that you just want to install secure code to update the system code. I will leave my previous answer as I believe that it also provides useful information.

+1
source

Source: https://habr.com/ru/post/949210/


All Articles