4

I have created an Integer Spinner with values

min (5), max (15) and initialValue (12) and wrapAround (true).

Once the spinner reaches the max (15) value during increment, instead of resetting the value to min (5) as it says in the documentation, it is being reset to value 10 (max (15) - min (5))

public final void setWrapAround​(boolean value)

Sets the value of the property wrapAround.

Property description:

The wrapAround property is used to specify whether the value factory should be circular. For example, should an integer-based value model increment from the maximum value back to the minimum value (and vice versa).

Note: Decrement works properly, once it reaches the min (5) value, Spinner value automatically set to max (15)

public class IntSpinnerTest extends Application
{
  @Override
  public void start(Stage stage) throws Exception
  {
    var spinner = new Spinner<Integer>();

    var factory = new SpinnerValueFactory.IntegerSpinnerValueFactory(5, 15, 12);
    factory.setWrapAround(true);

    spinner.setValueFactory(factory);

    stage.setScene(new Scene(new BorderPane(spinner), 400, 200));

    stage.setTitle("IntSpinnerTest");
    stage.centerOnScreen();
    stage.show();
  }

  public static void main(String[] args)
  {
    launch(args);
  }
}
Community
  • 1
  • 1
Venkata Raju
  • 4,866
  • 3
  • 27
  • 36

2 Answers2

3

This is a known bug: JDK-8193286. The submitter included a workaround—subclassing IntegerSpinnerValueFactory:

package sample; 

import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory; 

public final class IntSpinnerValueFactory extends IntegerSpinnerValueFactory { 

  public IntSpinnerValueFactory(final int min, final int max) { 
    super(min, max); 
  } 

  public IntSpinnerValueFactory(final int min, final int max, final int initialValue) { 
    super(min, max, initialValue, 1); 
  } 

  @Override 
  public void increment(final int steps) { 
    final int min = getMin(); 
    final int max = getMax(); 
    final int currentValue = getValue(); 
    final int newIndex = currentValue + steps * getAmountToStepBy(); 
    setValue(newIndex <= max ? newIndex : (isWrapAround() ? (newIndex - min) % (max - min + 1) + min : max)); 
  } 

} 

Note: Workaround has been slightly modified based on recommendations.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • Looks like this is second bug in `SpinnerValueFactory.IntegerSpinnerValueFactory`. [First one](https://stackoverflow.com/questions/36549829/javafx-spinner-empty-text-nullpointerexception/36570474#comment94547539_36570474) (They have fixed this `NullPointerException` bug in `DoubleSpinnerValueFactory` but not in `IntegerSpinnerValueFactory`. – Venkata Raju Dec 27 '18 at 21:37
  • There appears to be a workaround for this issue which I edited my answer to include. – Slaw Dec 27 '18 at 21:40
  • 2
    Also, I took a look at the fix for the other bug you linked to. They definitely only fixed the problem for `DoubleSpinnerValueFactory`. There doesn't seem to be a way around it either as the problem is located in an internal property listener. – Slaw Dec 27 '18 at 21:50
  • Bug submitter missed `final` once. In `increment()` method parameter . – Venkata Raju Dec 27 '18 at 21:54
  • 2
    You should change the last statement to `setValue(newIndex <= max ? newIndex : (isWrapAround() ? (newIndex - min) % (max - min + 1) + min : max));` make arbitrary permutations of `increment`/ `decrement` operations yield the same result. (Sorry, previous comment's version did not work `wrapAround = false`) – fabian Dec 27 '18 at 22:07
-1

I have similar problem with IntegerSpinner - but wrapping from -11 to 12 (negative to positive) - on reaching -11 or 12 it returns to zero. Solution was to make List spinner with Strings. So that using or setting the values I've needed to convert string to integer and vc.