在不删除以前的圆的情况下在新位置绘制圆?

Draw circle in new position without removing previous circle?

其实我是想在每次双击的时候在新的位置画一个圆圈,而不是在圆圈之前去掉,需要注意的是,我用的是PictureBox.

public Point postionCursor { get; set; }
List<Point> points = new List<Point>();
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{

    postionCursor = this.PointToClient(new Point(Cursor.Position.X - 25, Cursor.Position.Y - 25));
    points.Add(postionCursor);
    pictureBox1.Invalidate();

    pictureBox1.Paint += new PaintEventHandler(pic_Paint);
}

private void pic_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
       g.SmoothingMode = SmoothingMode.AntiAlias;

    foreach (Point pt in points)
    {

        Pen p = new Pen(Color.Tomato, 2);
        SolidBrush myb = new SolidBrush(Color.White);
        g.DrawEllipse(p, postionCursor.X, postionCursor.Y, 20, 20);
        g.FillEllipse(myb, postionCursor.X, postionCursor.Y, 20, 20);
        p.Dispose();
    }

}

您没有在 foreach 循环中使用 pt 变量。

foreach (Point pt in points)
{
    using(Pen p = new Pen(Color.Tomato, 2))
    using(SolidBrush myb = new SolidBrush(Color.White))
    {
        g.FillEllipse(myb, pt.X, pt.Y, 20, 20);
        g.DrawEllipse(p, pt.X, pt.Y, 20, 20);
    }
}

在您的代码中,您只是为 points 列表中的每个 Point 覆盖相同位置的圆圈。

此外,正如 Reza 在评论中提到的,您无需在每次单击 PictureBox 时都附加 PaintEventHandler 事件处理程序,只需执行一次即可。

所以我开始思考,然后 Visual Studio-ing,也许我们甚至不需要 foreach 循环。我仍然维护一个列表,这样我们就知道用户点击了哪里,但是不需要循环遍历它并每次都重绘所有内容。

我意识到这不处理基础列表被修改的情况,原始样本也不处理。这是我的整个 Form1 class:

public partial class Form1 : Form
{
    private const int CircleDiameter = 20;
    private const int PenWidth = 2;

    private readonly List<Point> _points = new List<Point>();

    public Form1()
    {
        InitializeComponent();

        pictureBox1.Paint += (sender, args) =>
        {
            _points.ForEach(p => DrawPoint(p, args.Graphics));
        };
    }

    private void pictureBox1_DoubleClick(object sender, EventArgs e)
    {
        var cursorLocation = pictureBox1.PointToClient(Cursor.Position);
        _points.Add(cursorLocation);

        var circleArea = new Rectangle(
            cursorLocation.X - CircleDiameter/2 - PenWidth,
            cursorLocation.Y - CircleDiameter/2 - PenWidth,
            CircleDiameter + PenWidth*2,
            CircleDiameter + PenWidth*2);

        pictureBox1.Invalidate(circleArea);
    }

    private static void DrawPoint(Point point, Graphics graphics)
    {
        point.X -= CircleDiameter / 2;
        point.Y -= CircleDiameter / 2;

        using (var pen = new Pen(Color.Tomato, PenWidth))
        using (var brush = new SolidBrush(Color.White))
        {
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            graphics.DrawEllipse(pen, point.X, point.Y, CircleDiameter, CircleDiameter);
            graphics.FillEllipse(brush, point.X, point.Y, CircleDiameter, CircleDiameter);
        }
    }
}

更新 1: 所以我更新了代码以使用具有 foreach 循环的 Paint 事件。但是,我不会在每次添加圆圈时都使(和绘制)无效 - 没有必要这样做。仅通过绘制添加圆意味着控件仅使添加新圆的区域无效并重新绘制。

尝试在 DrawAllPoints 方法上设置断点。您会看到它仅在完全失效操作期间发生,例如最小化和恢复。

更新二: 经过进一步交谈,我同意 Invalidate 方法更优越。代码更新为使用 Invalidate 和一个矩形来使无效。

现在看起来非常像 OP :)