16

I am making a GUI using JavaFx and I need sliders that only allow integers to ever be selected.

I know I can use snapToTicks, but while pulling the "knob", it can still represent a non-integer value. I would like to get rid of that. It messes up other components linked to it.

Basically, I want something like Swing's JSlider, but with JavaFx. Is it possible? I have been searching but I can't find anything.

Vishrant
  • 15,456
  • 11
  • 71
  • 120
Mr Redstoner
  • 478
  • 3
  • 6
  • 19

2 Answers2

20

You can simply add a listener to the valueProperty of the Slider and then you can either set the integer value of the new Number value:

slider.valueProperty().addListener((obs, oldval, newVal) -> 
    slider.setValue(newVal.intValue()));

or alternatively you can use integer rounding using Math.round:

slider.valueProperty().addListener((obs, oldval, newVal) ->
    slider.setValue(Math.round(newVal.doubleValue())));
DVarga
  • 21,311
  • 6
  • 55
  • 60
  • that's a pretty good idea, I just don't like the rounding down (for reason see my comment on SkyWalker). I still might use it though. – Mr Redstoner Jul 31 '16 at 09:32
  • You can also use integer rounding like `((int) Math.round(newVal.doubleValue()))`. Both approach just simply doesn't allow to have the "knob" between integer values. – DVarga Jul 31 '16 at 09:58
  • that sound way better, though I would still like to know if there is a more legitimate way. – Mr Redstoner Jul 31 '16 at 10:16
  • 1
    Where is the praise MVC when we need it, JavaFX? Coming from Swing, this is really an ugly solution. – piegames Jun 19 '17 at 15:21
  • @piegames I cannot see nothing really unforgivable in this approach (be honest - I guess you saw many much more ugly things in Swing, SWT or JavaFX or even in Winforms or WPF too;)). Some things can be done more elegantly in some of them, some thing in the other half. This approach sleeps under the aegis of simplicity, but anyways, if this solution hurts your design pattern senses, you can still implement your own Slider (skinning will be simpler in JavaFX9 as it is promised). – DVarga Jun 19 '17 at 19:43
  • 2
    hmm ... always feeling dirty when changing a property in a listener (even if we seem to get away with it in fx more often than in good ol' swing). Also I would guess (didn't try) the UX to be a feel a bit unexpected which never-ever should happen. Did you (OP) try a conditional binding in the dependent controls taking the value only when the slider's adjustingProperty is false? – kleopatra Apr 25 '18 at 08:33
  • @kleopatra Since this was for a personal project and I haven't needed it since, I've never experimented with making it better myself. Feel free to put together and post another answer. Going of of my reputation, people still sometimes stumble upon this question :) – Mr Redstoner Oct 10 '19 at 11:00
14

In FXML:

<Slider fx:id="availableReproSelector" 
        blockIncrement="1.0" 
        cache="true" 
        majorTickUnit="1.0" 
        max="4.0" 
        min="1.0" 
        minorTickCount="0" 
        showTickLabels="true" 
        showTickMarks="true" 
        snapToTicks="true" 
        value="1.0" 
        />

Or in Java:

Slider slider = new Slider(1, 4, 1);
slider.setBlockIncrement(1);
slider.setMajorTickUnit(1);
slider.setMinorTickCount(0);
slider.setShowTickLabels(true);
slider.setSnapToTicks(true);

The key here is the snap to ticks option combined with a proper combination of tick units. This setting results in the following slider which can only be used to select values ranging from 1 to 4 :

can only select int values ranging from 1 to 4

sirolf2009
  • 819
  • 8
  • 15
Arthur Vaïsse
  • 1,551
  • 1
  • 13
  • 26