如何通过类与鼠标点击实现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
相关产品推荐
相关产品推荐

