Search code examples
javafxspinnerlocaltime

How to display (the hours of) a local time in a spinner in JavaFx


How do I set the value of SpinnerValueFactory<LocalTime> valueFactory = new SpinnerValueFactory<LocalTime>() in a spinner?

Attempting to set and display the value in the spinner editor with hrsSpinner.getValueFactory().setValue(valueFactory); , Java tells me:

The method setValue(LocalTime) in the type SpinnerValueFactory<LocalTime> is not applicable for the arguments (SpinnerValueFactory<LocalTime>).

Another approach I've tried is hrsSpinner.setValueFactory(valueFactory);. I get no errors. But the hours are initially not displayed in the spinner editor until I've clicked on the spinner to increment or decrement the hours.

Any ideas how I can solve my problem? Here is a sample of my code I'm using

Calendar calendar = new GregorianCalendar();
int hour;
this.hour = calendar.get(Calendar.HOUR_OF_DAY);

if(hourRadioButton.isSelected() == true) 
        {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh");    

            ObservableList<String> hours = FXCollections.observableArrayList(String.valueOf(hour));
            SpinnerValueFactory<LocalTime> valueFactory = new SpinnerValueFactory<LocalTime>() {

                {
                    setConverter(new LocalTimeStringConverter(formatter,null));
                }

                @Override
                public void decrement(int steps) {
                    if(getValue() == null)
                    {
                        setValue(LocalTime.now());
                    }
                    else
                    {
                        LocalTime localTime = (LocalTime) getValue();
                        setValue(localTime.minusHours(1));
                    }                   
                }

                @Override
                public void increment(int steps) {
                    if (this.getValue() == null)
                    {
                        setValue(LocalTime.now());
                    }
                    else 
                    {
                        LocalTime localTime = (LocalTime) getValue();
                        setValue(localTime.plusHours(1));
                    }               
                }               
            };

            //hrsSpinner.setValueFactory(valueFactory);
            hrsSpinner.getValueFactory().setValue(valueFactory);
        }

Thank you very much in advance for your time and help!!! AvJoe


Solution

  • hrsSpinner.getValueFactory() is an expression of type SpinnerValueFactory<LocalTime>. Using setValue on this is not possible with this parameter and it wouldn't do what you want.

    Use the setter for the valueFactory property instead:

    hrsSpinner.setValueFactory(valueFactory);
    

    This way of setting the value factory seems to stem from the bad practice of using the setter of the property object instead of using the more concise and thus easier to parse version using the setter corresponding to the property. The version using the property object's setter would be

    hrsSpinner.valueFactoryProperty().set(valueFactory);
    

    in this case.

    Furthermore I don't recommend mixing Calendar and java.time API. If you've got the choice, go with the java.time api completely. It provides the same functionality and is much easier to use imho. E.g. assuming you wanted to use the calendar to truncate the value to full hours, you could use truncateTo instead:

    SpinnerValueFactory<LocalTime> factory = new SpinnerValueFactory<LocalTime>() {
    
        {
            setValue(defaultValue());
        }
    
        private LocalTime defaultValue() {
            return LocalTime.now().truncatedTo(ChronoUnit.HOURS);
        }
    
        @Override
        public void decrement(int steps) {
            LocalTime value = getValue();
            setValue(value == null ? defaultValue() : value.minusHours(steps));
        }
    
        @Override
        public void increment(int steps) {
            LocalTime value = getValue();
            setValue(value == null ? defaultValue() : value.plusHours(steps));
        }
    
    
    };
    Spinner<LocalTime> spinner = new Spinner<>();
    spinner.setValueFactory(factory);