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

如何结合List与MouseEventArgs绘制多个图形?

实现结合List与MouseEventArgs绘制多个图形的完整方案

先说说你的现有代码已经搭好了不错的基础:Cycle类负责椭圆绘制逻辑,用List存储起点和终点来记录每个图形的绘制信息。接下来咱们一步步把功能补全,实现完整的多图形绘制效果:

1. 完善基础变量定义

首先在Form1里补充几个关键变量,保证拖动状态和临时图形的记录逻辑能跑通:

// 标记是否正在拖动绘制图形
private bool moving = false;
// 临时存储当前正在绘制的图形的起点和终点
private Point Start;
private Point End;
// 存储所有已完成绘制的图形的起点与终点
private List<Point> star = new List<Point>();
private List<Point> endd = new List<Point>();
// 实例化Cycle类,用来执行绘制操作
private Cycle cycleDrawer = new Cycle();

2. 补全MouseMove与MouseUp事件逻辑

MouseMove要实时触发Panel重绘,显示正在拖动的临时图形;MouseUp时把完成的图形信息存入List,结束拖动状态:

private void Panel1_MouseMove(object sender, MouseEventArgs e)
{
    if (moving)
    {
        End = e.Location;
        // 触发Panel重绘,实时预览拖动中的图形
        Panel1.Invalidate();
    }
}

private void Panel1_MouseUp(object sender, MouseEventArgs e)
{
    if (moving)
    {
        moving = false;
        End = e.Location;
        // 将完成的图形的起点、终点存入List
        star.Add(Start);
        endd.Add(End);
        // 重绘Panel,显示所有已完成的图形
        Panel1.Invalidate();
    }
}

3. 实现Panel的Paint事件——核心绘制逻辑

这一步是把List里存储的所有已完成图形,以及当前正在拖动的临时图形都绘制出来,还要处理起点在终点右侧/下方的情况:

private void Panel1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    // 绘制所有已完成的椭圆
    for (int i = 0; i < star.Count; i++)
    {
        Point s = star[i];
        Point ePt = endd[i];
        // 计算椭圆的左上角坐标、宽高(兼容拖动方向)
        float x = Math.Min(s.X, ePt.X);
        float y = Math.Min(s.Y, ePt.Y);
        float width = Math.Abs(ePt.X - s.X);
        float height = Math.Abs(ePt.Y - s.Y);
        // 调用Cycle类的Draw方法绘制,这里用蓝色画刷举例
        cycleDrawer.Draw(g, Brushes.Blue, x, y, width, height);
    }

    // 如果正在拖动,绘制临时的椭圆(用红色画刷区分预览状态)
    if (moving)
    {
        float x = Math.Min(Start.X, End.X);
        float y = Math.Min(Start.Y, End.Y);
        float width = Math.Abs(End.X - Start.X);
        float height = Math.Abs(End.Y - Start.Y);
        cycleDrawer.Draw(g, Brushes.Red, x, y, width, height);
    }
}

4. 优化Cycle类的设计(可选)

你的Cycle类现在继承Form1其实没必要,它只负责绘制逻辑,改成普通类更合理,还能避免不必要的继承关系:

public class Cycle
{
    public void Draw(Graphics G, Brush b, float x, float y, float w, float h)
    {
        // 增加判断,避免宽高为0时的绘制异常
        if (w > 0 && h > 0)
        {
            G.FillEllipse(b, x, y, w, h);
        }
    }
}

5. 绑定事件到Panel(如果没在设计器绑定的话)

在Form的构造函数里把Panel的事件绑定好,确保事件能正常触发:

public Form1()
{
    InitializeComponent();
    // 绑定Panel的各类事件
    Panel1.MouseDown += Panel1_MouseDown;
    Panel1.MouseMove += Panel1_MouseMove;
    Panel1.MouseUp += Panel1_MouseUp;
    Panel1.Paint += Panel1_Paint;
}

这样一来,你就能实现完整功能:在Panel上按住鼠标拖动可绘制椭圆,拖动过程中会显示红色预览,松开鼠标后椭圆会被保存到List中,所有已绘制的蓝色椭圆都会一直保留在Panel上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:37:48