将画线图像绘制到Picturebox图像中

时间:2017-10-05 18:16:35

标签: c# .net winforms paint picturebox

在我的表单中,我有2个picturebox控件。我在pictureBox1上加了一个蓝色背景图片,然后单独留下pictureBox2控件。使用下面的代码,我可以在picturebox1图片上方绘制箭头。

目标:在我的pictureBox1_MouseUp活动中,我想将我在pictureBox1上绘制的所有箭头添加到pictureBox2

问题问题发生在pictureBox1_MouseUp事件中,当我写pictureBox2.Image = pictureBox1.Image时,它没有添加我在pictureBox1上绘制的绘制箭头。它只添加我在表单加载事件中指定的pictureBox1图像。

    private bool isMoving = false;
    private Point mouseDownPosition = Point.Empty;
    private Point mouseMovePosition = Point.Empty;
    private List<Tuple<Point, Point>> lines = new List<Tuple<Point, Point>>();
    Pen _Pen;

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {

        if (isMoving)
        {
            if (pictureBox1.Image == null) e.Graphics.Clear(Color.White);

            // Add this line for high quality drawing:
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;

            AdjustableArrowCap bigArrow = new AdjustableArrowCap(5, 5);
            _Pen = new Pen(Color.IndianRed, 3);
            _Pen.CustomEndCap = bigArrow;
            e.Graphics.DrawLine(_Pen, mouseDownPosition, mouseMovePosition);
            _Pen.Dispose();
        }
    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        isMoving = true;
        mouseDownPosition = e.Location;
    }

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

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {

        if (isMoving)
        {
            lines.Add(Tuple.Create(mouseDownPosition, mouseMovePosition));
        }
        isMoving = false;

        pictureBox2.Image = pictureBox1.Image;
    }

enter image description here

测试1 :(更改了pictureBox1_Paint代码)

使用此代码,它会在pictureBox2上绘制箭头,但看起来它正在绘制多个箭头。

        if (isMoving)
        {
            if (pictureBox1.Image == null) e.Graphics.Clear(Color.White);

            // Add this line for high quality drawing:
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;

            AdjustableArrowCap bigArrow = new AdjustableArrowCap(5, 5);
            _Pen = new Pen(Color.IndianRed, 3);
            Bitmap BitImg = (Bitmap)pictureBox1.Image;
            _Pen.CustomEndCap = bigArrow;
            using (var graphics = Graphics.FromImage(BitImg))
            {
                graphics.DrawLine(_Pen, mouseDownPosition, mouseMovePosition);
            }
            pictureBox1.Image = BitImg;
            _Pen.Dispose();
        } 

enter image description here

测试2 :(我从paint事件中获取代码并粘贴了MouseMove事件并进行了一些修改。这使用了太多的内存而且它没有在pictureBox1上绘制但箭头现在在pictureBox2中可见)

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (isMoving)
        {
            mouseMovePosition = e.Location;

            if (isMoving)
            {

                AdjustableArrowCap bigArrow = new AdjustableArrowCap(5, 5);
                _Pen = new Pen(Color.IndianRed, 3);
                BitImg = new Bitmap(pictureBox1.Image);                    
                _Pen.CustomEndCap = bigArrow;
                using (var graphics = Graphics.FromImage(BitImg))
                {
                    graphics.SmoothingMode = SmoothingMode.HighQuality;
                    graphics.DrawLine(_Pen, mouseDownPosition, mouseMovePosition);
                }

                _Pen.Dispose();
            }

            pictureBox1.Invalidate();

        }
    }

enter image description here

2 个答案:

答案 0 :(得分:1)

这里有两个问题:

  1. 您在Control上绘制而不是在图像上绘制。图像保持不变。

  2. pictureBox1pictureBox2都指的是同一张图片。更改图像时,下一个绘制事件将影响两个控件。

  3. 因此,在pictureBox1_Paint中,您需要创建pictureBox1.Image的副本(尝试使用Bitmap),然后在其上绘制并将更新的图像分配给pictureBox1.Image。它会自动绘制。

答案 1 :(得分:1)

将所有行绘制到pictureBox1: enter image description here

只绘制最后一行到pictureBox1: enter image description here

pictureBox2控件中,将Paint事件添加到pictureBox2_Paint

我建议你让笔和帽全局变化:

// Make pen and cap global varriable to boost the perfomane.
// Create and delete them each draw will cost alot of CPU
Pen pen = new Pen(Color.IndianRed, 3);
AdjustableArrowCap bigArrow = new AdjustableArrowCap(5, 5);

Form1()事件中,添加以下行:

pen.CustomEndCap = bigArrow;

并执行以下操作:

public partial class Form1 : Form
{
    private bool isMoving = false;
    private Point mouseDownPosition = Point.Empty;
    private Point mouseMovePosition = Point.Empty;
    private List<Tuple<Point, Point>> lines = new List<Tuple<Point, Point>>();

    public Form1()
    {
        InitializeComponent();
        pen.CustomEndCap = bigArrow;
    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        isMoving = true;
        mouseDownPosition = e.Location;
    }

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

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        if (isMoving)
        {
            lines.Add(Tuple.Create(mouseDownPosition, mouseMovePosition));
            pictureBox2.Invalidate();
        }
        isMoving = false;
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        if (isMoving)
        {
            if ((sender as PictureBox).Image == null) e.Graphics.Clear(Color.White);

            // Add this line for high quality drawing:
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;

            e.Graphics.DrawLine(pen, mouseDownPosition, mouseMovePosition);

            // If you want draw all previous lines here, add bellow code:
            //foreach (var line in lines)
            //{
            //    e.Graphics.DrawLine(pen, line.Item1, line.Item2);
            //}
        }
    }

    private void pictureBox2_Paint(object sender, PaintEventArgs e)
    {
        if ((sender as PictureBox).Image == null) e.Graphics.Clear(Color.White);

        e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
        foreach (var line in lines)
        {
            e.Graphics.DrawLine(pen, line.Item1, line.Item2);
        }
    }
}

上面的代码画线到PictureBox控件,而不是图像,这允许你删除一些行或清除你绘制到picturebox的所有行,如果你想在以后。

如果您想直接绘制图像,事情更容易,您根本不需要pictureBox2_Paint

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    if (isMoving)
    {
        // You event don't need this line
        //lines.Add(Tuple.Create(mouseDownPosition, mouseMovePosition));

        if (pictureBox1.Image != null)
        {
            using (var g = Graphics.FromImage(pictureBox1.Image))
            {
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.DrawLine(pen, mouseDownPosition, mouseMovePosition);
            }
            pictureBox2.Image = pictureBox1.Image;
        }
    }
    isMoving = false;
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    if (isMoving)
    {
        if ((sender as PictureBox).Image == null) e.Graphics.Clear(Color.White);

        e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
        e.Graphics.DrawLine(pen, mouseDownPosition, mouseMovePosition);
    }
}

private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
}