当ControlsFX RangeSlider的方向为垂直时,滑块的响应速度较慢。

7
当将setOrientation设置为Orientation.HORIZONTAL时,滑块的移动非常平滑,但当将setOrientation设置为Orientation.VERTICAL时,移动会有延迟。
下面是最小化的复现代码:
package org.example;

import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.RangeSlider;

public class App extends Application {

    @Override
    public void start(Stage stage) {

        RangeSlider rangeSliderVertical = new RangeSlider();
        rangeSliderVertical.setOrientation(Orientation.VERTICAL);
        rangeSliderVertical.setMinHeight(500);
        rangeSliderVertical.setMax(100);
        rangeSliderVertical.setMin(0);
        rangeSliderVertical.setHighValue(100);
        rangeSliderVertical.setLowValue(0);

        RangeSlider rangeSliderHorizontal = new RangeSlider();
        rangeSliderHorizontal.setMinWidth(500);
        rangeSliderHorizontal.setMax(100);
        rangeSliderHorizontal.setMin(0);
        rangeSliderHorizontal.setHighValue(100);
        rangeSliderHorizontal.setLowValue(0);
        rangeSliderHorizontal.setOrientation(Orientation.HORIZONTAL);

        FlowPane vBoxWithSliders = new FlowPane();
        VBox.setVgrow(vBoxWithSliders, Priority.ALWAYS);
        HBox.setHgrow(vBoxWithSliders, Priority.ALWAYS);

        vBoxWithSliders.setAlignment(Pos.CENTER);
        vBoxWithSliders.getChildren().addAll(rangeSliderVertical, rangeSliderHorizontal);

        var scene = new Scene(vBoxWithSliders, 600, 600);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

}

有没有关于如何在垂直方向上实现RangeSlider平滑移动的提示?

enter image description here


我在使用Windows 10 (i7-7700)、Java 20.0.2 (Eclipse Adoptium)、JavaFX 21.0.0和ControlsFX 11.1.2的代码中没有看到任何延迟。 - undefined
我把所有的拇指都移动了一遍。它们都移动得很顺畅。也许你可以在帖子中添加一个GIF来展示延迟? - undefined
当我分别拖动拇指时,它们也能平稳移动,但当我点击轨道并移动两个拇指时,拇指会跳动。我会查看视觉文档。 - undefined
我在我的端上注意到了这个问题(JavaFX 21,JDK 17,ControlsFX 11.1.2)。实际上,它还有另一个问题,就是在垂直方向拖动轨道时范围会突然增加(仅限垂直方向)。水平方向没有问题。已更新问题中的gif以供参考。 - undefined
我之前并没有尝试移动整个范围,只是单独移动了一些滑块。现在我也能看到问题所在了。 - undefined
显示剩余6条评论
1个回答

5
这是RangeSliderSkin中的一个错误。现有的代码包括对lowValueProperty()highValueProperty()的以下监听器:
    registerChangeListener(rangeSlider.lowValueProperty(), e -> {
        positionLowThumb();
        rangeBar.resizeRelocate(rangeStart, rangeBar.getLayoutY(), 
        rangeEnd - rangeStart, rangeBar.getHeight());
    });
    registerChangeListener(rangeSlider.highValueProperty(), e -> {
        positionHighThumb();
        rangeBar.resize(rangeEnd-rangeStart, rangeBar.getHeight());
    });

请查看源代码:https://github.com/controlsfx/controlsfx/blob/master/controlsfx/src/main/java/impl/org/controlsfx/skin/RangeSliderSkin.java

rangeBar.resizeRelocate()rangeBar.resize()的调用假设范围滑块具有水平方向。 (您可以将此视为仅layoutX和/或width的栏可以更改。 layoutYheight都设置为其当前值。)在layoutChildren()方法中重新绘制范围栏之前,会纠正范围栏的错误布局。 但是,我认为在调用layoutChildren()之前,可能会处理其他拖动事件,从而导致对拇指位置的错误计算。

我在ControlsFX存储库中有一个分支:https://github.com/james-d/controlsfx/tree/master,它修复了这个问题。

    registerChangeListener(rangeSlider.lowValueProperty(), e -> {
        positionLowThumb();
        if (isHorizontal()) {
            rangeBar.resizeRelocate(rangeStart, rangeBar.getLayoutY(),
                    rangeEnd - rangeStart, rangeBar.getHeight());
        } else {
            rangeBar.resize(rangeBar.getWidth(), rangeEnd - rangeStart);
        }
    });
    registerChangeListener(rangeSlider.highValueProperty(), e -> {
        positionHighThumb();
        if (isHorizontal()) {
            rangeBar.resize(rangeEnd - rangeStart, rangeBar.getHeight());
        } else {
            rangeBar.resizeRelocate(rangeBar.getLayoutX(), rangeStart,
                    rangeBar.getWidth(), rangeEnd - rangeStart);
        }
    });

我已经提交了这个问题作为Issue 1521,同时也提交了一个pull request
请随意克隆并构建我的分支作为临时措施,直到(如果)这个pull request被接受。

1
@droid 以下是我成功的方法:
  1. 克隆我的ControlsFX分支。
  2. 在IntelliJ中,选择文件 -> 打开,找到克隆仓库中的build.gradle文件。选择“作为项目打开”。这将创建一个新的IntelliJ项目。
  3. 在新项目中,选择构建 -> 构建controlsfx。这将在build文件夹下创建一个jar文件。
  4. 回到你自己的项目,在pom.xml中注释掉controlsfx的依赖。这将在你的module-info.java文件中创建一个错误。
  5. 选择文件 -> 项目结构 -> 外部库,将创建的jar文件添加为库。
- undefined
编辑:我认为我的“新”问题可能与我还用于RangeSlider的这个“修复”有关:https://stackoverflow.com/questions/76889910/java-controlsfx-rangeslider-css-issue - undefined
是的,我认为以上就是为什么它在我的主要项目中无法工作的原因 - 因为我在修复高低滑块时使用了旧的RangeSliderSkin。谢谢James_D。你理解得很好 :) - undefined
1
@droid 只是更新一下,这些拉取请求现在已经合并到主分支中了。 - undefined
太好了,感谢你的工作。 - undefined
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接