How to maintain ratio in values of JavaFX Spinner

pollux :

I have two spinners and a toggle button in my JavaFX application, and I've also set them editable

Spinner<Integer> hSelector = new Spinner<>(1,15000,1000,1);
Spinner<Integer> wSelector = new Spinner<>(1,15000,1000,1);
hSelector.setEditable(true);
wSelector.setEditable(true);
ToggleButton lock = new ToggleButton("lock");

When this lock toggle button is selected I want to maintain the ratio in values of hSelector and wSelector. So I tried following,

lock.selectedProperty().addListener((observable, oldValue, newValue) -> {
    if(newValue){
        hSelector.getValueFactory().valueProperty().addListener((ob, ov, nv) -> {
            wSelector.getEditor().setText(String.valueOf((nv * wSelector.getValue()) / ov));
        });
        wSelector.getValueFactory().valueProperty().addListener((ob, ov, nv) -> {
            hSelector.getEditor().setText(String.valueOf((nv * hSelector.getValue()) / ov));
        });
    }
});

But this did not work well. The problem is that when lock is selected and I change the value of one spinner and then I just focus(by clicking in text field of spinner) them both one by one, their value changes automatically even when I don't edit the values.

Now, my questions, What is the correct way to maintain the ratio in values of these spinners?, what is the problem in my method? and how to remove the behavior of maintaining ratio after lock is un-selected.

VGR :

Do not add a new listener every time the toggle button changes. “Add listener” means the method literally adds a listener to the existing set of listeners, so as your code is written, if the user were to select the toggle button ten times, you would have ten listeners on each spinner.

The correct approach is to add one listener to each Spinner. Each listener should do nothing if the toggle button is not selected. You will want to keep the spinner values’ ratio in a private field, for the listeners to use.

private double ratio = 1;

// ...

lock.selectedProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue) {
        hSelector.commitValue();
        wSelector.commitValue();
        ratio = (double) hSelector.getValue() / wSelector.getValue();
    }
});

hSelector.getValueFactory().valueProperty().addListener((ob, ov, nv) -> {
    if (lock.isSelected()) {
        wSelector.getValueFactory().setValue((int) (nv / ratio));
    }
});
wSelector.getValueFactory().valueProperty().addListener((ob, ov, nv) -> {
    if (lock.isSelected()) {
        hSelector.getValueFactory().setValue((int) (nv * ratio));
    }
});

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=135539&siteId=1