【问题标题】:How to set a slider to fix to positions?如何设置滑块以固定位置?
【发布时间】:2023-12-29 15:22:01
【问题描述】:

我有一个滑块,我要求它固定到整数 1-23。因此,如果用户将其从 1 移动,他们最终会得到 1-23 的任何数字,这与双精度值不同。这个滑块的作用是当一个时钟,你拖动它会出现不同的时间。

我的第一次尝试:

private final int MIN_CHANGE = 1;
....

timeSlider.setMax(23);

....

timeSlider.valueProperty().addListener((obs, oldValue, newValue) -> {
    if (!timeSlider.isValueChanging()) {
        if (Math.abs(newValue.intValue()) > MIN_CHANGE) {
            timeSlider.setValue(newValue.intValue());
        }
    }
});

这或多或少有效,但仅适用于单击,不适用于拖动。

如果 getValue 是双精度值,如何在拖动时将滑块固定为 1-23 等整数?

我面临的另一个问题是拖动 pm/am 时变化并不突然。

timeSlider.valueChangingProperty().addListener((obs, wasChanging, isChanging) -> {
    if (isChanging) {
        if(timeSlider.getValue() < 12.99) {
            labelTest.textProperty().bind(Bindings.format("%.0f:00am", timeSlider.valueProperty()));
        } else {
            labelTest.textProperty().bind(Bindings.format("%.0f:00pm", timeSlider.valueProperty()));
        }
    }
});

【问题讨论】:

  • @ItachiUchiha 正是我想要的!谢谢你。上午/下午更新呢?拖动时如何让它更新,而不仅仅是点击?现在我可以从头拖到尾,除非我在 13 点之后单击任何值,否则上午/下午不会改变。
  • 除非我点击 13 之后的任何值,否则上午/下午不会改变。我不明白这个。你能解释一下你最后发生了什么吗?
  • 我的意思是我可以将滑块从 0 拖动到 15 并且绑定将保持在 am,除非我单击 13 之后的任何值,只有当绑定更改为 pm 时。我只是通过在valueProperty() 而不是valueChangingProperty() 中执行此操作来解决此问题

标签: java javafx slider


【解决方案1】:

尝试将snapToTicks 设置为 true 并将主要刻度间距设置为 23:

timeSlider.setSnapToTicks(true);
timeSlider.setMajorTickUnit(23.0);
timeSlider.setBlockIncrement(23.0);
timeSlider.setMinorTickCount(0.0); // Disable minor ticks

【讨论】:

    【解决方案2】:

    为了使其与数字对齐,我使用了 FXML 场景构建器中提供的 blockIncrement、majorTickUnit 和 snapToTicks,感谢 ItachiUchiha。

    作为参考,我使用了以下设置

    min="1.0"
    max="23.0" 
    blockIncrement="1.0" 
    majorTickUnit="1.0" 
    minorTickCount="0" 
    showTickMarks="true" 
    snapToTicks="true"
    

    最后,为了解决 am/pm 不更新的问题,我将 am/pm 绑定的方法更改为以下

    timeSlider.valueProperty().addListener((obs, oldValue, newValue) -> {
        if (timeSlider.isValueChanging()) {
            if (newValue.intValue() < 12) {
                labelTest.textProperty().bind(Bindings.format("%.0f:00am", timeSlider.valueProperty()));
            } else {
                labelTest.textProperty().bind(Bindings.format("%.0f:00pm", timeSlider.valueProperty()));
            }
        }
    });
    

    【讨论】: