JavaFX ScrollBar值混淆

时间:2014-10-08 23:43:42

标签: javafx javafx-2 scrollbar

我有一个带有Canvas和ScrollBar的简单JavaFX应用程序。 Canvas充当虚拟画布,其内容可以使用ScrollBar滚动。

Canvas的宽度为500像素,但Canvas的逻辑宽度为1000像素。 我已将ScrollBar的最大值设置为1000,ScrollBar的可见量设置为500。 问题是当ScrollBar一直向右滚动时的值 ScrollBar是1000,而不是500。 逻辑上,当ScrollBar一直向右滚动时,应该有一些方法来确定实际的滚动偏移,这似乎是不可能的。 请建议如何获得所需的滚动量。谢谢

以下是向左滚动的示例。 滚动条看起来不错。其可见宽度是窗口大小的50%。

enter image description here

这是向右侧中间滚动的示例。 问题很明显。 Canvas已向右滚动500像素,但如果Canvas正确滚动到中途,它将仅滚动250像素。

enter image description here

以下是向右滚动的示例。 enter image description here

import javafx.application.Application;
import javafx.beans.value.*;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.stage.Stage;

public class Sc extends Application {

    public ScrollBar scrollBar;
    double scrolled;
    Canvas canvas;

    @Override
    public void start(Stage stage) {
        VBox vbox = new VBox();
        Scene scene = new Scene(vbox);
        stage.setScene(scene);

        canvas = new Canvas(500, 100);
        scrollBar = new ScrollBar();
        scrollBar.setMin(0);
        scrollBar.setMax(1000);
        scrollBar.setVisibleAmount(500);
        vbox.getChildren().addAll(canvas, scrollBar);
        draw();

        scrollBar.valueProperty().addListener(new ChangeListener<Number>() {
            public void changed(ObservableValue<? extends Number> ov,
                Number old_val, Number new_val) {
                scrolled = new_val.doubleValue();
                draw();
            }
        });

        stage.show();
    }

    private void draw()
    {
        GraphicsContext graphics = canvas.getGraphicsContext2D();
        graphics.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
        Stop[] stops = new Stop[] { new Stop(0, Color.BLACK), new Stop(1, Color.RED)};
        LinearGradient lg = new LinearGradient(0, 0, 1, 0, true, CycleMethod.NO_CYCLE, stops);
        graphics.setFill(lg);
        graphics.fillRect(0-scrolled, 30, 1000, 40);
    }

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

1 个答案:

答案 0 :(得分:3)

这样想:

minmaxvalue是滚动条的逻辑值。 value介于minmax之间,当且仅当滚动条一直滚动到左侧(或顶部,垂直滚动条)时,min等于visibleAmount )。当且仅当滚动条尽可能向右(或底部)滚动时,它等于max。

thumbSize / trackSize = visibleAmount / (max - min) 属性实际上只是一个可视属性,用于确定“拇指”的大小。这种关系就像是

visibleAmount

value会影响实际像素与“逻辑单位”之间的关系;但是,它不会改变[min, max]1000 - canvas.getWidth()的整个范围内变化的事实。

因此,您需要对代码进行的唯一更改是将滚动条的最大值设置为可以滚动的最大值(不是您正在绘制的图像的大小),即import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.control.ScrollBar; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.paint.CycleMethod; import javafx.scene.paint.LinearGradient; import javafx.scene.paint.Stop; import javafx.stage.Stage; public class ScrollBarExample extends Application { private final static double TOTAL_WIDTH = 1000 ; @Override public void start(Stage stage) { VBox vbox = new VBox(); Scene scene = new Scene(vbox, 500, 130); stage.setScene(scene); Canvas canvas = new Canvas(500, 100); ScrollBar scrollBar = new ScrollBar(); scrollBar.setMin(0); scrollBar.setMax(TOTAL_WIDTH - canvas.getWidth()); scrollBar.setVisibleAmount(scrollBar.getMax() * canvas.getWidth() / TOTAL_WIDTH); vbox.getChildren().addAll(canvas, scrollBar); draw(canvas, scrollBar.getValue()); scrollBar.valueProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) { draw(canvas, scrollBar.getValue()); } }); stage.show(); } private void draw(Canvas canvas, double scrollAmount) { GraphicsContext graphics = canvas.getGraphicsContext2D(); graphics.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); Stop[] stops = new Stop[] { new Stop(0, Color.BLACK), new Stop(1, Color.RED)}; LinearGradient lg = new LinearGradient(0, 0, 1, 0, true, CycleMethod.NO_CYCLE, stops); graphics.setFill(lg); graphics.fillRect(0-scrollAmount, 30, TOTAL_WIDTH, 40); } public static void main(String[] args) { launch(args); } }

{{1}}