【问题标题】:Retrieving Correct PictureBox Images From Array从数组中检索正确的 PictureBox 图像
【发布时间】:2018-04-10 07:08:15
【问题描述】:

在我的表单中,我试图让我的撤消按钮起作用。我使用pictureBox1 来绘制我的方块并使用pictureBox2 来显示绘制的历史。

功能

在 Picturebox mouseup 事件中,我将所有绘制的对象添加到列表数组中,所以稍后当我单击撤消按钮时,它应该会显示我绘制的矩形的历史记录。因此,如果我在 picturebox1 上有 4 个矩形并单击撤消 picturebox2 应该显示 3 个矩形。如果我再次单击撤消按钮,picturebox2 应该会显示 2 个矩形。

问题是当我单击撤消按钮时它没有按我希望的那样工作。它不断地向我显示我绘制的所有矩形,并且没有显示我绘制对象的历史。

代码

    Point startArea;   // mouse-down position
    Point currentArea; // current mouse position
    bool drawingBox;     // busy drawing
    List<Rectangle> rectangleList = new List<Rectangle>(); //previous rectangles
    List<Image> ImageCollection = new List<Image>();
    int ImageHistory;

    private void Test_Load(object sender, EventArgs e)
    {
        pictureBox1.Image = Properties.Resources.background;

    }

    private Rectangle getRectangle()
    {
        return new Rectangle(
            Math.Min(startArea.X, currentArea.X),
            Math.Min(startArea.Y, currentArea.Y),
            Math.Abs(startArea.X - currentArea.X),
            Math.Abs(startArea.Y - currentArea.Y));
    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        currentArea = startArea = e.Location;
        drawingBox = true;

    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        currentArea = e.Location;
        if (drawingBox)
        {
            pictureBox1.Invalidate();
        }
    }



    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        if(drawingBox)
        {
            drawingBox = false;
            var rc = getRectangle();
            if(rc.Width > 0 && rc.Height > 0)
            {
                rectangleList.Add(rc);
                pictureBox1.Invalidate();
            }
        }
        ImageHistory++;
        ImageCollection.Add(pictureBox1.Image);

    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        if (rectangleList.Count > 0)
        {
            using (var g = Graphics.FromImage(pictureBox1.Image))
            {
                g.DrawRectangles(Pens.Black, rectangleList.ToArray());
                pictureBox1.Invalidate();
            }
        }

        if(drawingBox)
        {                                                
            e.Graphics.DrawRectangle(Pens.Red, getRectangle());

            pictureBox1.Invalidate();                
        }

    }

    private void button1_Click(object sender, EventArgs e)
    {
        ImageHistory--;
        pictureBox2.Image = ImageCollection[ImageHistory];
    }
}

【问题讨论】:

    标签: c# .net image winforms gdi+


    【解决方案1】:

    更改以下行

    ImageCollection.Add(pictureBox1.Image);
    

    ImageCollection.Add((Image)pictureBox1.Image.Clone())
    

    【讨论】:

      【解决方案2】:

      虽然接受的答案可以解决问题,但在尝试解决问题时应该考虑一些重要的注意事项:

      • 您不需要使用List&lt;Image&gt; 作为撤消缓冲区,它会占用大量内存。而且目前由于您不处理未使用的图像,您的应用程序很快就会陷入内存泄漏。

      • 使用List&lt;Rectangle&gt; 作为撤消缓冲区就足够了。它明显使用更少的内存。您无需跟踪要处置的任何东西,它也不需要处置。

      • 1234563这样您就不需要更改图片框的图像,您应该只在绘图表面上绘制矩形而不是在图像上绘制它们。最后,如果您需要导出包含所有矩形的图像,只需将它们绘制在位图上并导出图像即可。
      • 您可以将Undo 方法和Redo 方法和CanUndo 属性封装在DrawingSurface 控件中,并在应用程序中使用这些方法,而不是直接将这些逻辑放在按钮后面。

      示例

      你可以看一个关于Draw multiple freehand Poly-line or Curve drawing - Adding Undo Feature的例子。

      【讨论】:

        猜你喜欢
        • 2022-12-14
        • 1970-01-01
        • 2022-01-12
        • 1970-01-01
        • 2011-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多