Paint Drawline Image into Picturebox Image

2019-05-29 18:58发布

In my Form, I have 2 picturebox controls. I loaded a blue background image on pictureBox1 and left pictureBox2 control alone. With the code below I'm able to draw arrows on top of my picturebox1 image.

Goal: On my pictureBox1_MouseUp event I want to add all the arrows which I drew on pictureBox1 to pictureBox2.

Issue: The problem is on my pictureBox1_MouseUp event when I wrote pictureBox2.Image = pictureBox1.Imageit doesn't add the painted arrow which I drew on pictureBox1. It only adds the pictureBox1 image that I assigned in my form load event.

    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

Test 1: (Changed pictureBox1_Paint code)

With this code, it draws the arrow on pictureBox2, but it looks like it is drawing multiple arrows.

        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

Test 2: (I took the code from the paint event and pasted it MouseMove Event with some modifications. This uses too much memory and it doesn't draw on pictureBox1 but the arrow is now visible in 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条回答
SAY GOODBYE
2楼-- · 2019-05-29 19:46

Draw all lines to pictureBox1: enter image description here

Draw only last line to pictureBox1: enter image description here

In pictureBox2 control, add Paint event to pictureBox2_Paint.

I suggest you make pen and cap global varriable:

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

In Form1() event, add this line:

pen.CustomEndCap = bigArrow;

and do as following:

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

Above code draw lines to PictureBox control, not to image, this allow you remove some lines or clear all lines you draw to picturebox if you want later.

If you want draw directly to image, things event much easier, you don't need pictureBox2_Paint at all:

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)
{
}
查看更多
我想做一个坏孩纸
3楼-- · 2019-05-29 19:54

You have two problems here:

  1. You paint on Control rather than an image. The image remains unchanged.

  2. Both pictureBox1 and pictureBox2 refer to the same image. When you change the image, both controls will be affected on the next paint event.

So in pictureBox1_Paint you need create a copy of pictureBox1.Image (try using Bitmap), then paint on it and assign the updated image to pictureBox1.Image. It will be painted automatically.

查看更多
登录 后发表回答