我想在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();
}
}
}
1条答案
按热度按时间mm5n2pyu1#
看了你的代码,我恐怕不得不说:这是全错了。
很抱歉这么直率,但是你绝对不能使用控件。CreateGraphics!!
Graphics objgraphics
对象。存储
Graphics
对象(几乎)总是错误的!相反,您必须使用从控件的
Paint
事件中的e.Graphics
参数获取的值。注意
Graphics
不包含任何图形,它是一个用于在关联的Bitmap
或控件表面上绘图的工具。有一个很好的方法
DrawCurve
可以画出平滑的线条,你给它一个Pen
和一个Points
数组。这就是我们要用的。
让我们回到基本点:如何创建图形?现在我们知道需要在
Paint
事件中调用DrawCurve
:这就引出了下一个问题:
还有隐藏的第三个问题:
第一个很简单;你创建了一个
Pen
,描边宽度为5.5像素,如果你愿意,你可以给予它一个线条(破折号),太。
现在来看阵列:在其最简单的形式,这是很容易的。
在
MouseMove
事件中,将当前的Location
存储在一个点列表中。首先,我们在类级别声明它:然后,我们开始填充它,只要按下左键:
注意最后一行:在控件上调用
Invalidate
会触发system调用Paint
事件。这可能看起来很复杂,但这是唯一正确的方法,因为它保证了当某些其他原因需要时,同样的绘图也会发生。我们需要绘图,因为我们更改了应该绘制的数据。但是有许多外部原因,最有名的是
Minimize/maximize
序列,它也会清除绘图并触发Paint
事件。所以我们需要配合windows绘制其控件的方式!只有这样图形才会持久**。另外,注意我们没有使用数组,因为我们不知道我们需要多少个
Points
,而是使用一个List
,然后将其转换为Array
。让我们为简单的情况编写
Paint
事件:注意,我在
using
子句中创建了Pen
,这是确保正确处理Pen
的一种廉价而安全的方法。还要注意我们如何将
List
强制转换为Array
!上面的代码本身就可以工作,并允许您徒手画一条线。
但是下一行怎么办?它不应该连接到第一行,所以我们不能只是添加更多的点!
因此,我们不仅需要一个点列表,而且需要更多点列表。事实上,我们需要点列表的列表:
每当松开鼠标时,我们将当前曲线添加到其中:
注意我是如何使用从
List
到List
的强制转换来强制执行复制的,否则只会分配引用,然后在下一行中清除。我们再次触发
Paint
事件,作为最后要做的事情。现在,我们应该更改
Paint
事件以显示所有线,包括当前正在绘制的线和所有之前绘制的线。现在我们基本上完成了徒手绘制部分。
所以我们回到你最初的问题:如何将绘图复制到秒
Panel
?那么,您已经将所有内容存储在
curves
数据结构中。所以你有两个选择或者简单地在
panel2_Paint
事件中使用相同的数据,或者如果您需要将数据复制并更改到,则可以调整为不同的大小。以下是仍然缺少的东西:
Serialize
,DrawToBitMap
)drawAction
类来存储所有需要的内容)drawAction
类)Stacks
和Queues
)BackgroundImage Bitmap
)下面是一个清除代码:
我注意到你原来的代码允许你用左右键画两种不同的笔画宽度。这就说明这段代码不是很好。谁会a)想到这一点,b)只满足于两种笔画宽度。
请阅读这篇文章,我解释了一点关于创建一个类,可以存储一个笔宽,颜色等,以便您可以改变然后在您绘制的线条。