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

JavaFX Canvas添加沙粒后不更新渲染问题求助

解决JavaFX下落沙游戏点击无沙粒渲染的问题

以下是几个排查和修复方向:

1. 检查鼠标坐标转沙粒网格坐标的逻辑

鼠标点击获取的是Canvas上的像素坐标,需要转换成沙粒对应的网格坐标(即point.getX()和point.getY()),必须确保转换正确:

// 鼠标点击事件中的坐标转换示例
canvas.setOnMouseClicked(e -> {
    // 获取Canvas上的相对坐标
    double mouseX = e.getX();
    double mouseY = e.getY();
    // 转换成网格坐标(取整,因为沙粒是按网格排列的)
    int gridX = (int) (mouseX / SandApplication.GRAIN_SIZE);
    int gridY = (int) (mouseY / SandApplication.GRAIN_SIZE);
    // 确保坐标在Canvas的网格范围内
    if (gridX >=0 && gridX < WIDTH / SandApplication.GRAIN_SIZE 
        && gridY >=0 && gridY < HEIGHT / SandApplication.GRAIN_SIZE) {
        grainMap.put(new Point(gridX, gridY), new Grain(...)); // 替换成你的Grain构造逻辑
    }
});

如果转换时未取整、未做边界判断,沙粒可能被添加到Canvas可视区域外,导致无法显示。

2. 临时固定背景色排除颜色冲突

你的draw方法每次都会生成随机背景色,有可能沙粒颜色和背景色高度接近甚至完全一致,导致视觉上看不到沙粒。可以先把背景改成固定颜色测试:

public void draw(){
    GraphicsContext gc = getGraphicsContext2D();
    // 固定背景色为黑色,方便观察沙粒
    gc.setFill(Color.BLACK);
    gc.fillRect(0, 0, WIDTH, HEIGHT);

    grainMap.forEach(((point, grain) -> {
        System.out.println(grain.getGrainColour());
        gc.setFill(grain.getGrainColour());
        gc.fillRect(point.getX() * SandApplication.GRAIN_SIZE, point.getY() * SandApplication.GRAIN_SIZE,
                SandApplication.GRAIN_SIZE,
                SandApplication.GRAIN_SIZE);
    }));
}

如果此时能看到沙粒,说明是颜色冲突的问题,后续再调整背景色逻辑即可。

3. 验证grainMap的元素是否正确添加

确认鼠标点击后,grainMap中确实存在新添加的沙粒:

  • 可以在鼠标点击事件中打印map的size:System.out.println(grainMap.size());,查看点击后数值是否增长。
  • 如果使用自定义的Point类作为key,必须正确实现equals()和hashCode()方法,否则HashMap无法正确识别相同坐标的Point,可能导致添加失败或遍历不到:
// 自定义Point类的示例实现
public class Point {
    private int x;
    private int y;

    // 构造方法、getter

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return x == point.x && y == point.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

4. 确认Canvas的尺寸与实际显示一致

确保代码中使用的WIDTH和HEIGHT与Canvas在场景中实际显示的尺寸一致:

  • 如果Canvas是通过布局管理器(比如BorderPane)添加的,可能需要绑定Canvas的尺寸到父容器,或者在初始化时明确设置:
// 初始化Canvas时绑定尺寸到场景
canvas.widthProperty().bind(scene.widthProperty());
canvas.heightProperty().bind(scene.heightProperty());
// 同时在draw方法中使用canvas.getWidth()/canvas.getHeight()替代固定值
public void draw(){
    GraphicsContext gc = getGraphicsContext2D();
    double canvasWidth = getWidth();
    double canvasHeight = getHeight();
    gc.setFill(Color.BLACK);
    gc.fillRect(0, 0, canvasWidth, canvasHeight);
    // 后续绘制逻辑使用canvasWidth/canvasHeight做边界判断
}

如果WIDTH/HEIGHT小于实际显示尺寸,背景填充不完整,或者沙粒画在未填充区域被覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:00:59