javafx binding multiple properties for a single purpose

43 Views Asked by At

I have multiple data sets and am trying to write a javafx program to graph selected data using a MVVM architecture. There are three key properties I have bound between my view and view model : start, step (scale) and selected data set. They work as expected. When I change a data set, I reset the start to 0 and the step to 1. If I select a max button, the start is changed to 0 and the step is changed to the maximum possible value depending on data size.

I have started with binding these properties accordingly which work as expected, but I need to know when something is changed so I can redraw it. I have listeners also set up for each of the properties. It feels wrong to me to bind properties and then have to create change listeners so I know when things changed. Furthermore if multiple properties are changed, I get several asynchronous change events which initiate the graph to be redrawn each time. It would be better to handle all of the changes simultaneously instead of one after another.

  • When I select the spinner, the step increases correctly and the redrawMatches method is called once to draw the plot to the correct scale.
  • When I move the slider, the start increases correctly and the redrawMatches method is called to redraw my plot to the left or right.
  • When the Choice box is selected, a new data set is retrieved from the Model and the start and step are reset to 0 and 1, respectively, resulting in two redraws.
  • There is also a Max button (not shown) which figures out and sets the maximum possible step and at the same resets the start to 0, resulting in two redraws.

Here are some properties and Listeners from the controller :

        /***************************************************************************
         * 
         *                              C H O I C E B O X
         * 
         **************************************************************************/    

        chromosomeChoiceBox.setItems(_VPViewModel.CHROMOSOMES);
        chromosomeChoiceBox.valueProperty().bindBidirectional(_VPViewModel.chromProperty());
        _VPViewModel.chromProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                System.out.println("Chromosome changed from " + oldValue + " to " + newValue);
                //_VPViewModel.dataUpdate();
                startSlider.setValue(_VPViewModel.getXStart());
                stepSpinner.getValueFactory().setValue(1);
                setupSlider();
            }
        });     
        
        /***************************************************************************
         * 
         *                            S P I N N E R
         * 
         **************************************************************************/    
               
        // Value factory.
        SpinnerValueFactory<Integer> valueFactory = 
                new SpinnerValueFactory.IntegerSpinnerValueFactory(1, Integer.MAX_VALUE, _VPViewModel.getStep());
        
        stepSpinner.setValueFactory(valueFactory);
        stepSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
        stepSpinner.getValueFactory().valueProperty().bindBidirectional(_VPViewModel.stepSpinnerValue());
        stepSpinner.setEditable(true);
        
        _VPViewModel.stepSpinnerValue().addListener(new ChangeListener<Integer>() {             
            @Override
            public void changed(ObservableValue<? extends Integer> observable, Integer oldValue, Integer newValue) {
                System.out.println("Step changed from " + oldValue + " to " + newValue);                
                redrawMatches();
            }
        });
        
        /***************************************************************************
         * 
         *                              S L I D E R
         * 
         **************************************************************************/    

        startSlider.setLabelFormatter(_VPViewModel.getStringConverter());
        
        _sliderMin = 0;
        _sliderValue = _sliderMin;        
        _sliderEnabled = true;        
        setupSlider();
        // set slider to XStart
        startSlider.setValue(_VPViewModel.getXStart());
        startSlider.valueProperty().bindBidirectional(_VPViewModel.startProperty());
        startSlider.valueProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                System.out.println("Start changed from " + oldValue + " to " + newValue);               
                redrawMatches();
            }
        });         
        
    }    
1

There are 1 best solutions below

0
mgillett On

Maybe someone will find this interesting or helpful...

Not sure if this qualifies as a work-around or a solution, but I added a flag to my controller class, defaulted to true:

    private boolean _bAllowedToDraw = true;

Any GUI events, I know will only change a single property, I leave as is. GUI Events which affect multiple property, I incorporate the flag.

For example, I changed my choiceboxListener :

         _VPViewModel.chromProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                System.out.println("Chromosome changed from " + oldValue + " to " + newValue);
                _bAllowedToDraw = false;
                _VPViewModel.dataUpdate();
                startSlider.setValue(_VPViewModel.getXStart());
                stepSpinner.getValueFactory().setValue(1);
                setupSlider();
                _bAllowedToDraw = true;
                redrawMatches();
            }
        });     

I did the same for my Max Button Listener.

Inside my redrawMatches() class, I wrapped the implementation with

    if _bAllowedToDraw {
        /* 
           existing code
                .
                .
                .
        */
    }