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

时间:2015-05-15 22:17:18

标签: java javafx

在下面的示例中,滚动条的块增量设置为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);
    }
}

2 个答案:

答案 0 :(得分:1)

我无法给出一个很好的解释

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

的流程

希望它能够:)

答案 1 :(得分:1)

ScrollBar.adjustValue(position)方法负责此行为。

它基本上有三个步骤:

  1. 确定&#34;位置值&#34;通过使用按下鼠标的相对位置
  2. 确定&#34;新值&#34;通过使用块增量值(这是我想要的值)
  3. 确定是否使用&#34;位置值&#34;或者#34;新值&#34;。
  4. 因为我总是想要&#34;新的价值&#34;我刚刚从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()) );
            }
        }
    };