You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

缩放Canvas后调整ScrollPane内部尺寸以消除空白区域

问题描述

实现了点击按钮缩放Canvas游戏区域的功能,整体运行正常,但缩放后ScrollPane中原Canvas所在位置出现空白区域。尝试多种调整ScrollPane尺寸的方法均无效,希望让ScrollPane的内部区域随Canvas尺寸变化,消除空白区域。

现有代码

Java代码

public class GameView {
    @FXML public Canvas gameField;
    @FXML public ScrollPane scrollPane; 

    public void doZoomOut() {
        Scale scale = new Scale(gameField.getScaleX() * 0.8, gameField.getScaleY() * 0.8);
        gameField.getTransforms().add(scale);

        scrollPane.resize(gameField.getWidth(), gameField.getHeight()); //无效
        scrollPane.setPrefViewportWidth(gameField.getWidth()); //无效
        scrollPane.setPrefViewportHeight(gameField.getHeight()); //无效
        //Fit to Width/Height也无效
        scrollPane.setPrefWidth(gameField.getWidth()); //无效
    }
}

FXML代码

<ScrollPane fx:id="scrollPane" fitToHeight="true" fitToWidth="true" style="-fx-background-color: transparent;" stylesheets="@../../../style.css">
    <styleClass>
               <String fx:value="scroll-bar" />
               <String fx:value="corner" />
               <String fx:value="thumb" />
    </styleClass>
    <Canvas fx:id="gameField" height="700.0" width="1200.0" />
</ScrollPane>

问题截图

问题截图

解决方案

问题根源:你用Transforms.add(Scale)只是对Canvas做了视觉层面的缩放,但Canvas本身的width和height属性并没有改变,ScrollPane识别的内容区域还是Canvas的原始尺寸,所以缩放后会出现空白。

方法一:用Group包裹Canvas(推荐)

ScrollPane的内容如果是Group,Group会自动根据子节点的变换(比如Scale)调整自身边界,让ScrollPane能正确感知内容的实际大小,自动适配消除空白。

修改FXML代码

<ScrollPane fx:id="scrollPane" fitToHeight="true" fitToWidth="true" style="-fx-background-color: transparent;" stylesheets="@../../../style.css">
    <styleClass>
               <String fx:value="scroll-bar" />
               <String fx:value="corner" />
               <String fx:value="thumb" />
    </styleClass>
    <!-- 用Group包裹Canvas -->
    <Group>
        <Canvas fx:id="gameField" height="700.0" width="1200.0" />
    </Group>
</ScrollPane>

原Java缩放逻辑无需额外修改,缩放后Group会自动更新自身边界,ScrollPane会跟着调整内部区域,空白自然消失。

方法二:直接修改Canvas尺寸并适配绘图缩放

如果不想用Group,可以直接修改Canvas的实际尺寸,同时在绘图时应用缩放比例,让ScrollPane识别到Canvas的新尺寸:

修改Java代码

public class GameView {
    @FXML public Canvas gameField;
    @FXML public ScrollPane scrollPane;
    // 记录当前缩放比例
    private double scaleX = 1.0;
    private double scaleY = 1.0;
    // 记录Canvas原始尺寸
    private final double originalWidth = 1200.0;
    private final double originalHeight = 700.0;

    public void doZoomOut() {
        scaleX *= 0.8;
        scaleY *= 0.8;
        
        // 修改Canvas的实际尺寸
        gameField.setWidth(originalWidth * scaleX);
        gameField.setHeight(originalHeight * scaleY);
        
        // 重新绘制内容时需应用缩放比例
        redrawGameField();
    }

    private void redrawGameField() {
        GraphicsContext gc = gameField.getGraphicsContext2D();
        gc.clearRect(0, 0, gameField.getWidth(), gameField.getHeight());
        
        // 应用缩放后再绘图
        gc.save();
        gc.scale(scaleX, scaleY);
        // 这里写你的游戏绘图逻辑,比如:
        // gc.fillRect(100, 100, 50, 50);
        gc.restore();
    }
}

这种方法需要同步维护缩放比例和Canvas尺寸,绘图时手动适配缩放,适合需要精确控制Canvas尺寸的场景。


内容的提问来源于stack exchange,提问作者unclled

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 22:23:11