滚动条 - 块增量似乎可变不固定

Scrollbar - the block increment seems variable not fixed

在下面的示例中,滚动条的块增量设置为 100。但是,实际值似乎是 1 - 100 之间的值,具体取决于您在轨迹栏上单击的位置。

当 运行 示例尝试在轨道中间大致单击几次以向下滚动。当我这样做时,我得到如下输出:

ScrollBar Max: 400.0
LayoutY: -100.0
LayoutY: -200.0
LayoutY: -300.0
LayoutY: -375.0 // this varies depending on the click location

无论我在轨道上的哪个位置单击,我都希望滚动单位改变 100。 (即,一次只能看到一个标签)。

这是一个常见的滚动功能吗?如果是这样,有没有办法关闭它?

代码如下:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Orientation;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class ScrollBarSSCCE extends Application
{

    @Override
    public void start(Stage stage)
    {
        int labelWidth = 300;
        int labelHeight = 100;

        String[] styles =
        {
            "-fx-background-color: #336699;",
            "-fx-background-color: #996633;",
            "-fx-background-color: #ff0000;",
            "-fx-background-color: #00ff00;",
            "-fx-background-color: #0000ff;"
        };

        VBox vb = new VBox();

        for (int i = 0; i < styles.length; i++)
        {
            Label label = new Label();
            label.setPrefWidth( labelWidth );
            label.setPrefHeight( labelHeight );
            label.setStyle( styles[i] );
            vb.getChildren().add( label );
        }

        ScrollBar sc = new ScrollBar();
        sc.setOrientation(Orientation.VERTICAL);
        sc.setLayoutX(labelWidth);
        sc.setMin(0);
        sc.setMax( (styles.length - 1) * labelHeight);
        System.out.println("ScrollBar Max: " + sc.getMax());
        sc.setPrefHeight( labelHeight );
        sc.setUnitIncrement( labelHeight / 2 );
        sc.setBlockIncrement( labelHeight );

        sc.valueProperty().addListener(
            (ObservableValue<? extends Number> ov, Number old_val, Number new_val) ->
            {
                double y = -new_val.doubleValue();
                System.out.println("LayoutY: " + y);
                vb.setLayoutY( y );
            });

        Group root = new Group();
        root.getChildren().addAll(vb, sc);

        Scene scene = new Scene(root, labelWidth+20, labelHeight);
        stage.setScene(scene);
        stage.setTitle("ScrollBar SSCCE");
        stage.show();
    }

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

不好解释

System.out.println("block increment: " +sc.getBlockIncrement()); 总是一样的,当我测试它时,它发生在两侧下降或上升,我认为它与 ScrollBar.adjustValue(position); 有关,所以如果我要提供某种解决方案,我会说在你最需要的时候调整 Value

//in your value listener you can add these codes
if(new_val.doubleValue() > old_val.doubleValue()){ //going down
     if(sc.getMax()-sc.getBlockIncrement() < Math.abs(y)){
         sc.adjustValue(1);
      }
}else{//going up
    if(old_val.doubleValue() == sc.getBlockIncrement()){
        sc.adjustValue(0);
    }
}

我认为您可能希望将 sc.setUnitIncrement(labelHeight/2); 设置为与 sc.setBlockIncrement(labelHeight); 相同,因为该代码可能会破坏 UnitIncrement

的流程

希望它能帮上忙:)

ScrollBar.adjustValue(position) 方法是造成此行为的原因。

基本上分为三个步骤:

  1. 根据鼠标按下的相对位置确定一个"position value"
  2. 使用块增量值确定"new value"(这是我想要的值)
  3. 判断是使用"position value"还是"new value"。

因为我一直想要 "new value",所以我刚刚从 adjustValue(...) 方法中删除了第 3 步。

这是自定义代码 ScrollBar:

ScrollBar sc = new ScrollBar()
{
    @Override
    public void adjustValue(double position)
    {
        // figure out the "value" associated with the specified position

        double posValue = ((getMax() - getMin()) * Utils.clamp(0, position, 1)) + getMin();

        double newValue;

        if (Double.compare(posValue, getValue()) != 0)
        {
            if (posValue > getValue())
            {
                newValue = getValue() + getBlockIncrement();
            }
            else
            {
                newValue = getValue() - getBlockIncrement();
            }

            setValue( Utils.clamp(getMin(), newValue, getMax()) );
        }
    }
};