簡體   English   中英

JavaFX Canvas.setScaleX/Y(2) 沒有縮放到兩倍大小

[英]JavaFX Canvas.setScaleX/Y(2) not scaling to twice the size

也許我誤解了一些基本的東西,但我正在試驗 JavaFX 並且很困惑為什么縮放 Canvas (使用.setScaleX/Y)的值為 2 不會導致 ZFCC790C72A861960DEZDC5 的兩倍寬

相關代碼是這樣的:(此時我沒有使用any.fxml)

public class Main extends Application {

    @Override
    public void start(Stage primaryStage){
        AnchorPane pane = new AnchorPane();
        Canvas canvas = new Canvas();
        canvas.setWidth(100);
        canvas.setHeight(100);
        canvas.getGraphicsContext2D().setFill(Color.BLUE);
        canvas.getGraphicsContext2D().fillRect(0,0,100,100);
        canvas.setScaleX(2);
        canvas.setScaleY(2);
        pane.getChildren().add(canvas);
        primaryStage.setScene(new Scene(pane, 200, 200));
        primaryStage.show();
    }


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

這導致 canvas 大約是 window 的 2/3(就寬度/高度而言,而不是面積)。 使用 3 的比例使它填滿整個 window(邊緣處有一個像素間隙),我不明白為什么。 我查看了文檔,但似乎 2 的比例因子應該導致兩倍的尺寸。

編輯:因此,根據下面的建議,將 canvas 翻譯為其寬度/高度的一半可以解決問題。 但是將它集中在 StackPane 中也是如此,所以我不明白為什么 AnchorPane 不會通過它的頂部/左邊緣來錨定它,如果它在縮放后真的是 200x200,就好像它通過它的 100x100 邊緣來錨定它一樣。 但是,如果 Canvas 是 100x100,那么如果只是在 StackPane 中居中,它是如何超出這些界限的呢?

EDIT2:通過一些實驗,我想我確認 AnchorPane 正在定位 Canvas “好像”它仍然是 100x100。 因此,通過將頂部和左側錨點設置為 50,我可以獲得與平移 50 或將其置於 StackPane 中一樣的結果。 但這意味着 Canvas 實際上是在“邊緣”之外“繪制”。 這肯定不對吧?

您在原始帖子中的編輯中添加的信息提供了該問題的大部分答案。

首先注意scaleXscaleY圍繞其中心縮放節點。 來自文檔:“定義沿該節點的 X 軸圍繞 object 的中心縮放坐標的因子。”

其次,請注意,應用於節點的轉換不會在該節點的布局計算中考慮。 布局文檔(參見“Visual Bounds vs Layout Bounds”部分):

因此,例如...如果使用ScaleTransition來脈沖按鈕的大小,則該脈沖 animation 不會干擾該按鈕周圍的布局。 如果應用程序希望將效果、剪輯或變換因素考慮到節點的布局中,則應將該節點包裝在Group中。

文檔中引用的最后一句話是指Group的布局邊界包括應用於該組的子級(但不應用於該組本身)的任何轉換這一事實。

要可視化正在發生的事情,請從 100x100 canvas 開始。 布局忽略縮放,因此您可以將其可視化為在應用縮放之前將 canvas 錨定到錨窗格的左上角。 然后 canvas 圍繞其中心進行縮放,將所有四個角在兩個維度上都推離中心 50 像素。 因此,錨窗格坐標系中 canvas 的邊界是從(-50, -50)(150, 150) 您可以通過添加來驗證這一點

System.out.println(canvas.getBoundsInParent());

舞台展示后。

有兩種解決方案。 一種是將 canvas 包裝在一個Group中。 Group的布局邊界將考慮 canvas 上的縮放:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage){
        AnchorPane pane = new AnchorPane();
        Canvas canvas = new Canvas();
        canvas.setWidth(100);
        canvas.setHeight(100);
        canvas.getGraphicsContext2D().setFill(Color.BLUE);
        canvas.getGraphicsContext2D().fillRect(0,0,100,100);
        canvas.setScaleX(2);
        canvas.setScaleY(2);
        
        Group group = new Group(canvas);
        AnchorPane.setTopAnchor(group, 0.0);
        AnchorPane.setLeftAnchor(group, 0.0);
        
        pane.getChildren().add(group);
        primaryStage.setScene(new Scene(pane, 200, 200));
        primaryStage.show();
    }


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

另一種解決方案是應用一個轉換,將 canvas 圍繞其左上角進行縮放:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage){
        AnchorPane pane = new AnchorPane();
        Canvas canvas = new Canvas();
        canvas.setWidth(100);
        canvas.setHeight(100);
        canvas.getGraphicsContext2D().setFill(Color.BLUE);
        canvas.getGraphicsContext2D().fillRect(0,0,100,100);

        Scale scale = new Scale(2,2);
        scale.setPivotX(0);
        scale.setPivotY(0);
        canvas.getTransforms().add(scale);

        pane.getChildren().add(canvas);
        primaryStage.setScene(new Scene(pane, 200, 200));
        primaryStage.show();
    }


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

您已經將 canvas 添加到窗格中,嘗試在pane.getChildren().add(canvas)之前 apply.setScaleX/Y 。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM