在不删除上一个圆圈的情况下在新位置画圈?

时间:2016-07-12 10:33:34

标签: c# winforms gdi+ picturebox

事实上,我希望每次双击时在新位置绘制圆圈而不在圆圈之前删除,应该注意的是,我使用了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();
    }

}

enter image description here

2 个答案:

答案 0 :(得分:4)

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

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);
    }
}

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

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

答案 1 :(得分:0)

所以我开始思考,然后是Visual Studio,或许我们甚至不需要foreach循环。我仍然维护一个List,以便我们知道用户点击的位置,但是不需要循环遍历它并且每次都重绘所有内容。

我意识到这并没有处理修改基础列表的情况,但原始样本也没有。这是我的整个Form1课程:

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方法上设置断点。您将看到它仅在完全失效操作期间发生,例如最小化和恢复。

更新2: 进一步聊天后,我同意Invalidate方法更优越。更新代码以使用带有矩形的无效以使其无效。

现在它看起来非常像OP:)