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

JavaFX中用setOnMouseMoved实现多圆绘制的问题及优化

JavaFX 点击-拖动绘制圆形解决方案

核心思路

别在鼠标移动事件里反复创建新圆形,通过三个阶段的事件配合实现需求:

  • 鼠标按下:确定圆心,创建临时预览圆
  • 鼠标拖动:实时更新临时圆的半径,实现拖拽预览效果
  • 鼠标释放:判断半径是否有效,有效则保留正式圆,无效则清理临时圆

完整代码实现

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class DrawCircle extends Application {

    private Circle tempCircle; // 拖拽时的预览圆
    private double centerX, centerY; // 记录圆心坐标

    @Override
    public void start(Stage primaryStage) {
        Pane root = new Pane();
        Scene scene = new Scene(root, 800, 600);

        // 鼠标按下:确定圆心,生成临时预览圆
        root.setOnMousePressed(event -> {
            centerX = event.getX();
            centerY = event.getY();
            tempCircle = new Circle(centerX, centerY, 0, Color.LIGHTBLUE);
            tempCircle.setStroke(Color.BLACK);
            tempCircle.setFill(Color.LIGHTBLUE.deriveColor(1, 1, 1, 0.5)); // 半透明填充
            root.getChildren().add(tempCircle);
        });

        // 鼠标拖动:实时计算并更新预览圆的半径
        root.setOnMouseDragged(event -> {
            if (tempCircle != null) {
                double dx = event.getX() - centerX;
                double dy = event.getY() - centerY;
                double radius = Math.sqrt(dx * dx + dy * dy); // 计算两点间距离作为半径
                tempCircle.setRadius(radius);
            }
        });

        // 鼠标释放:确认绘制,处理有效/无效圆
        root.setOnMouseReleased(event -> {
            if (tempCircle != null) {
                if (tempCircle.getRadius() > 0) {
                    // 半径有效,创建正式圆(或直接修改临时圆样式保留)
                    Circle finalCircle = new Circle(centerX, centerY, tempCircle.getRadius(), Color.LIGHTBLUE);
                    finalCircle.setStroke(Color.BLACK);
                    root.getChildren().remove(tempCircle);
                    root.getChildren().add(finalCircle);
                } else {
                    // 半径为0,移除临时圆
                    root.getChildren().remove(tempCircle);
                }
                tempCircle = null; // 重置预览圆引用
            }
        });

        primaryStage.setTitle("Draw Circle");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

问题解决说明

  1. 避免鼠标移动生成大量圆:用setOnMouseDragged代替setOnMouseMoved,仅维护一个临时预览圆,拖动时只更新半径而非创建新圆,彻底解决重复生成的问题。
  2. 过滤半径为0的无效圆:鼠标释放时判断预览圆半径是否大于0,只有满足条件才保留正式圆,否则直接移除临时圆,避免无效节点加入场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:10:06