2014-10-08 81 views
3

我有一個簡單的帶有Canvas和ScrollBar的JavaFX應用程序。 Canvas充當虛擬化畫布,其內容可以使用ScrollBar進行滾動。JavaFX ScrollBar值混淆

畫布的寬度爲500像素,但畫布的邏輯寬度爲1000像素。 我已將ScrollBar的最大值設置爲1000,並將ScrollBar的可見值設置爲500. 問題是,當滾動條一直滾動到右側時,滾動條的值爲1000,而不是500. 邏輯上,當ScrollBar一直滾動到右側,應該有一些方法來確定實際的滾動偏移量,這似乎不可能。 請建議如何獲得所需的滾動量。謝謝

以下是滾動到左側的示例。 滾動條看起來不錯。它的可見寬度是窗口大小的50%。

enter image description here

這裏是例子中途向右滾動。 這裏的問題很明顯。畫布向右滾動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); 
    } 
} 

回答

3

認爲它是這樣的:

minmaxvalue是滾動條的邏輯值。 value的範圍在minmax之間,並且等於min當且僅當滾動條一直滾動到左邊(或頂部,對於垂直滾動條)。當且僅當滾動條儘可能向右(或向下)滾動時,它等於max。

visibleAmount屬性實際上只是一個決定「拇指」大小的視覺屬性。的關係是一樣的東西

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); 
    } 
} 
+0

謝謝!這實際上是我在等待你的建議時開始做的。我只是覺得這個解決方案太hacky了,一定有更好的方法哈哈哈! – 2014-10-09 05:21:02