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

如何通过类与鼠标点击实现JavaFX中圆形的绘制显示?

JavaFX绘图程序:点击画布生成圆形功能修复

问题描述

我是JavaFX新手,正在开发一款简单的图形绘制程序。当前遇到的问题是:无法实现点击画布时生成圆形的功能。我希望先点击标注为“Circle”的按钮,之后点击画布就能生成圆形(同时使用SceneBuilder和IntelliJ进行开发)。

原代码

Shape抽象类

public abstract class Shape {
    double x;
    double y;
    double width;
    double height;
    public Color color = Color.WHITE;

    public void creatingShapes(double x, double y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public double getX() { return x; }
    public void setX(double x) { this.x = x; }
    public double getY() { return y; }
    public void setY(double y) { this.y = y; }
    public double getWidth() { return width; }
    public void setWidth(double width) { this.width = width; }
    public double getHeight() { return height; }
    public void setHeight(double height) { this.height = height; }
    public Color getColor() { return color; }
    public abstract void draw(GraphicsContext g);
}

Circle类

public class Circle extends Shape {
    @Override
    public void draw(GraphicsContext g) {
        g.setFill(color);
        g.fillOval(200,200,200,200);
        g.fillRect(getX(),getY(),getWidth(),getHeight());
        g.setStroke(Color.BLACK);
        g.strokeOval(getX(),getY(),getWidth(),getHeight());
    }
}

HelloController控制器类

public class HelloController {
    @FXML
    private Button logoutButton;
    @FXML
    private BorderPane scenePane;

    Stage stage;

    @FXML
    private ColorPicker myColorPicker;
    @FXML
    private ChoiceBox<String> myChoiceBox;

    @FXML
    private Button circle;
    @FXML
    private GraphicsContext g;

    private final Shape[] shapes = new Shape[500];
    Canvas canvas = new Canvas(310,333);

    boolean drawShape = true;
    int count = 0;
    private final Color currentColor = Color.BLUE;

    private final String[] menuAlternatives = {"Sparning", "Testing?", "Exit?"};

    public void onCircleClicked() {
        circle.setOnAction((event) -> addShape(new Circle()));
    }

    // 创建形状
    public void addShape(Shape shape) {
        shape.setColor(currentColor);
        shape.creatingShapes(10,10,150,100);
        shapes[count] = shape;
        count++;
        paintCanvas();
    }

    public void changeColor(ActionEvent event) {
        Color myColor = myColorPicker.getValue();
        scenePane.setBackground(new Background(new BackgroundFill(myColor, null, null)));
    }

    public void initialize() {
        g = canvas.getGraphicsContext2D();
    }

    public void paintCanvas() {
        g.setFill(Color.WHITE);
        g.fillRect(0,0,400,400);
        Arrays.stream(shapes, 0, count).forEach(s -> s.draw(g));
    }
}

问题拆解

  • 按钮逻辑错误:onCircleClicked重复绑定按钮点击事件,且直接生成固定位置的圆形,未标记“准备绘制圆形”的状态。
  • 画布无点击监听:未给Canvas添加鼠标点击事件,点击画布无法触发生成形状的操作。
  • Circle绘制冗余:draw方法包含多余的固定位置椭圆、矩形绘制代码,干扰正确图形显示。
  • 颜色变量不可修改:currentColor被声明为final,无法同步颜色选择器的选中值。
  • 画布未加入布局:创建的Canvas未添加到界面布局中,用户看不到也无法点击画布。

修复后的代码

修复后的Circle类

public class Circle extends Shape {
    @Override
    public void draw(GraphicsContext g) {
        g.setFill(color);
        // 以点击位置为中心绘制圆形,width/height作为直径
        g.fillOval(x - width/2, y - height/2, width, height);
        g.setStroke(Color.BLACK);
        g.strokeOval(x - width/2, y - height/2, width, height);
    }
}

修复后的HelloController类

import javafx.event.ActionEvent;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ColorPicker;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import java.util.Arrays;

public class HelloController {
    @FXML
    private Button logoutButton;
    @FXML
    private BorderPane scenePane;

    Stage stage;

    @FXML
    private ColorPicker myColorPicker;
    @FXML
    private ChoiceBox<String> myChoiceBox;

    @FXML
    private Button circleBtn;
    private GraphicsContext g;

    private final Shape[] shapes = new Shape[500];
    private Canvas canvas = new Canvas(310, 333);
    // 标记当前要绘制的形状类型,null表示不绘制
    private String currentShapeType = null;
    int count = 0;
    // 移除final修饰,允许更新颜色
    private Color currentColor = Color.BLUE;

    private final String[] menuAlternatives = {"Sparning", "Testing?", "Exit?"};

    // 点击Circle按钮时,设置当前要绘制的形状为圆形
    public void onCircleClicked() {
        currentShapeType = "CIRCLE";
    }

    // 创建形状,接收点击位置坐标
    public void addShape(Shape shape, double clickX, double clickY) {
        shape.setColor(currentColor);
        // 设置形状的位置为点击坐标,大小设为固定值(可按需调整)
        shape.setX(clickX);
        shape.setY(clickY);
        shape.setWidth(50);
        shape.setHeight(50);
        shapes[count] = shape;
        count++;
        paintCanvas();
    }

    public void changeColor(ActionEvent event) {
        Color myColor = myColorPicker.getValue();
        scenePane.setBackground(new Background(new BackgroundFill(myColor, null, null)));
        // 更新当前绘制颜色
        currentColor = myColor;
    }

    public void initialize() {
        g = canvas.getGraphicsContext2D();
        // 将画布添加到BorderPane的中心区域,确保界面可见
        scenePane.setCenter(canvas);

        // 给画布添加鼠标点击事件监听器
        canvas.setOnMouseClicked(event -> {
            // 如果当前有选中的形状类型,生成对应图形
            if ("CIRCLE".equals(currentShapeType)) {
                addShape(new Circle(), event.getX(), event.getY());
            }
        });

        // 初始化选择框选项
        myChoiceBox.getItems().addAll(menuAlternatives);
    }

    public void paintCanvas() {
        g.setFill(Color.WHITE);
        g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
        Arrays.stream(shapes, 0, count).forEach(s -> s.draw(g));
    }
}

关键修复说明

  • 调整按钮逻辑:点击Circle按钮仅标记当前要绘制的形状类型,而非直接创建形状。
  • 添加画布点击监听:通过canvas.setOnMouseClicked捕获点击坐标,根据标记的形状类型生成对应图形。
  • 优化Circle绘制:以点击位置为中心绘制圆形,移除冗余代码。
  • 更新颜色变量:取消currentColor的final修饰,同步颜色选择器的选中值。
  • 画布加入布局:将Canvas添加到BorderPane的中心,确保用户能看到并点击画布。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:50:26