从 Visual Studio 2013 的面板中复制手绘图

2024-01-27

我想在 Visual Studio 上以表单(图片框)徒手绘制,并在另一个面板/图片框上复制相同的图形(我绘制的)。 而且它们不应该是形成一条线的点,而是一条连续的线。请帮忙。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Pen p_white;

        bool draw = true;

        private Graphics objgraphics;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            Pen p_black = new Pen(new SolidBrush(Color.Black));

            if (draw)
            {
                objgraphics = panel1.CreateGraphics();

            }

        }

        /*private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            bool draw = true;
        }*/

        private void panel1_MouseMove_1(object sender, MouseEventArgs e)
        {
                      Rectangle rEllipse = new Rectangle();


            switch (e.Button)
            {

                case MouseButtons.Left:

                    rEllipse.X = e.X;
                    rEllipse.Y = e.Y;
                    rEllipse.Width = 5;
                    rEllipse.Height = 5;
                    objgraphics.DrawEllipse(System.Drawing.Pens.Black, rEllipse);
                    break;

                case MouseButtons.Right:

                    rEllipse.X = e.X;
                    rEllipse.Y = e.Y;
                    rEllipse.Width = 3;
                    rEllipse.Height = 3;
                    objgraphics.DrawEllipse(System.Drawing.Pens.Black, rEllipse);
                    break;

                default:
                    return;
           } 

        }

        /*private void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            bool draw = false;
        } */

        private void form_Paint(object sender, EventArgs e)
        {

        }

        private void panel2_Paint(object sender, PaintEventArgs e)
        {

            Pen p_black = new Pen(new SolidBrush(Color.Black));

            if (draw)
            {                objgraphics = panel1.CreateGraphics();

            }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}

看着你的代码恐怕我不得不说:这是都错了.

抱歉这么直白,但是你绝对不能使用control.CreateGraphics!

  • 首先要做的就是扔掉Graphics objgraphics object.

存储a(几乎)总是错误的Graphics object!

相反,您必须使用从e.Graphics中的参数Paint您的控件的事件。

注意Graphics 不包含任何图形,它是一个用于绘制到关联的工具Bitmap或控件的表面。

  • 接下来要做的就是了解手绘线条。通常人们可以看到您拥有的代码;但这是无用的,只是你在介绍中发现了多少愚蠢的事情的一个例子。忘了它。它总是看起来像垃圾,因为圆圈看起来永远不会平滑,一旦你更快地移动鼠标,伪线就会完全崩溃。

有一个不错的方法DrawCurve这将画出平滑的线条。你喂它一个Pen和一个数组Points.

这就是我们将要使用的。

让我们回到基础知识:如何创建图形?现在我们知道您需要致电DrawCurve in the Paint event:

e.Graphics.DrawCurve(somePen, somePointsArray);

这就提出了接下来的问题:

  • 什么是笔
  • 什么是 somePointsArray

还有一个隐藏的第三个问题:

  • 画更多线条怎么样?

第一个很简单;你创建一个Pen笔划宽度为 5.5 像素

Pen somePen = new Pen(Color.Blue, 5.5f); 

如果你愿意,你也可以给它一个线条样式(破折号)。

现在来说说数组:以最简单的形式,这也很容易。

In the MouseMove您存储当前的事件Location在点列表中。首先,我们在类级别声明它:

List<Point> currentLine = new List<Point>();

然后我们只要按下左键就开始填充:

private void panel1_MouseMove_1(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
    {
        currentLine.Add(e.Location);
        panel1.Invalidate();
    }  
}

注意最后一行:调用Invalidate在控件上触发system调用Paint事件。它可能看起来很复杂,但这是唯一正确的方法,因为它保证当某些情况下也会发生完全相同的绘图other理性使得它成为必要。

We需要绘制,因为我们更改了应该绘制的数据。但也有很多outside原因,最出名的是Minimize/maximize序列将清除绘图并触发Paint事件,也。所以我们需要合作随路windows绘制其控件!只有这样图形才会persist.

另外,请注意,我们不使用数组,因为我们不知道有多少Points我们会需要。相反,我们使用List然后将其投射到Array.

让我们编写代码Paint我们简单案例的事件:

private void panel1_Paint(object sender, PaintEventArgs e)
{
   using (Pen somePen = new Pen(Color.Blue, 5.5f) )
     if (currentLine.Count > 1) e.Graphics.DrawCurve(yourPen , currentLine.ToArray());
}

请注意,我已经创建了Pen in a using条款。这是一种廉价且安全的方法,可确保Pen已妥善处置。

另请注意我们如何投射List to an Array!

仅上面的代码就可以工作并允许您徒手画一条线。

但是下一行呢?它不应该连接到第一个,所以我们不能只是添加更多点!

所以我们不仅需要one点列表但是more除此之外,事实上,需要一个点列表的列表:

List<List<Point>> curves = new List<List<Point>>();

每当释放鼠标时,我们都会将当前曲线添加到其中:

private void panel1_MouseUp(object sender, MouseEventArgs e)
{
    if (currentLine.Count > 1) curves.Add(currentLine.ToList());  // copy!!
    currentLine.Clear();
    panel1.Invalidate();
}

请注意我如何使用来自List to List强制执行副本,否则仅分配引用,然后在下一行中清除..

我们再次触发Paint事件作为最后要做的事情。

我们现在应该改变Paint显示所有线条的事件,包括当前正在绘制的线条和所有先前绘制的线条..:

private void panel1_Paint(object sender, PaintEventArgs e)
{
    using (Pen somePen = new Pen(Color.Blue, 5.5f) )
    {
       if (currentLine.Count > 1) e.Graphics.DrawCurve(somePen, currentLine.ToArray());
       foreach (List<Point> lp in curves)
          if (lp.Count > 1) e.Graphics.DrawCurve(somePen, lp.ToArray());
    }
}

现在我们的手绘部分已经基本完成了。

所以我们回到你原来的问题:如何将绘图复制到second Panel?

好吧,你已经将所有内容存储在curves数据结构。

所以你有两个选择:要么简单地使用相同的数据panel2_Paint事件或者如果您需要复制和更改数据,也许会适应不同的大小。

以下是仍然缺少的东西:

  • 保存数据,保存绘图(Serialize, DrawToBitMap)
  • 用不同的笔和颜色绘图(创建一个drawAction类来存储您需要的所有内容)
  • 使用其他工具,如直线或矩形(创建一个drawAction class)
  • 清除绘图(见下文)
  • 撤消和重做(查看Stacks an Queues)
  • 当有大量行时进行缓存(将第一部分绘制到BackgroundImage Bitmap)

这是一个清除代码:

curves.Clear(); currentLine .Clear(); panel1.Invalidate();

我注意到您的原始代码允许您使用左右按钮以两种不同的笔画宽度进行绘制。仅此一点就说明这段代码不是很好。谁会a)想到这一点并且b)只满足于两个笔划宽度。

请阅读这个帖子 https://stackoverflow.com/questions/28714411/update-a-drawing-without-deleting-the-previous-one/28716887?s=5%7C0.1873#28716887我在其中解释了一些关于创建一个可以存储笔宽度、颜色等的类,以便您可以在绘制的线条之间进行更改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Visual Studio 2013 的面板中复制手绘图 的相关文章

随机推荐