更新graphics而不删除前一个
我在一个绘图方法中创build了这个
private void draws() { Bitmap bmp = new Bitmap(pictureBox17.Width, pictureBox17.Height); using (Graphics g = Graphics.FromImage(bmp)) { //define area do pictureBox17 e preenche a branco Brush brush = new SolidBrush(Color.White); Rectangle area = new Rectangle(0, 0, pictureBox17.Width, pictureBox17.Height); g.FillRectangle(brush, area); //desenha as linhas do rectangulo g.DrawLine(new Pen(Color.Black), esp, esp, esp, yWcorrigidoesp); // some more lines } pictureBox17.Image = bmp; }
它正是我想要的。 但想象一下,在此之后,我想更新完全相同的graphics,添加几行,而不必再次画全部,这可能吗? 显然我使用的方法
draws();
然后我想添加一些东西,任何提示?
做到这一点的方法是创build一个DrawAction
类,该类包含要绘制的所有数据: Point
数据, Pen
或Brush
等。
然后你创build并pipe理一个List<DrawAction> drawActions
,然后你有一个select:
-
您可以通过循环显示列表,在
PictureBox
或Panel
(或任何具有Paint
事件的控件)的Paint
事件中执行所有绘图。 -
或者您将新动作添加到您正在构build的
Bitmap Image
中。
有什么更好的确取决于:您是否期望通过用户操作进行dynamic绘图? 你想要一个撤销/重做选项? 然后,在控制面上进行实时绘图更适合。
或者是要修复或从固定数据集派生的事物列表,并且最终将其保存到磁盘。 这听起来更像是绘制到位图中。
两者也可以合并,也许收集一些行动,同时保留撤消选项(通过删除最后的列表项),并提供一个应用button,将他们泵入位图。
注意:绘制东西的关键是将绘图数据准备好在列表中,以便在需要时再使用它,扩展和删除列表,甚至更改它:这将是一个简单的双线程来完成行动和改变Pen
的Color
或Width
或LineStyle
或移动Points
等等等等!
当您创buildDrawAction
类时,如果您可以决定需要哪些操作,将会DrawAction
帮助。 如果你还不能,你仍然可以有更多的扩展类,有足够的成员来处理Graphics
类提供的所有选项: Drawxx
, Fillxxx
, Pen
属性, Colors
甚至可以放大。
对于初学者来说,一个Type,一个List<Point>
一个float PenWidth
和一个Color
将会做..
下面是一个简单的类, Paint
事件,添加一些testing动作和both
代码的例子:
- 一个button来做现场绘画和..
- ..一个应用的行动应用到位图
Image
的PictureBox
的行动。
testing数据是一行和一组Polylines
。
你应该开始改进,通过定义一个Enum
所有你想要使用的绘图动作types! 这将更好,更容易理解我编码的廉价字符types;-)types可以包括Rectangle, FilledRectangle, Ellipse, FilledEllipse, Line, Lines, Polygon, FilledPolygon, Text, Curve, Curves
,然后一些。 有了额外的一点,你也可以使用Image,GraphicsPath,Spline等。其他数据可以控制Rotation, Scaling, Gradients, Transparency
等。
List<DrawAction> actions = new List<DrawAction>(); public class DrawAction { public char type { get; set; } // this should be an Enum! public Color color { get; set; } public float penWidth { get; set; } // only one of many Pen properties! public List<Point> points { get; set; } // use PointF for more precision public DrawAction(char type_, Color color_, float penwidth_) { type = type_; color = color_; penWidth = penwidth_; points = new List<Point>(); } } private void pictureBox1_Paint(object sender, PaintEventArgs e) { Draw(e.Graphics, actions); } public void Draw(Graphics G, List<DrawAction> actions) { foreach (DrawAction da in actions) if (da.type == 'L' && da.points.Count > 1) using (Pen pen = new Pen(da.color, da.penWidth)) G.DrawLine(pen, da.points[0], da.points[1]); else if (da.type == 'P' && da.points.Count > 1) using (Pen pen = new Pen(da.color, da.penWidth)) G.DrawLines(pen, da.points.ToArray()); // else.. } private void button1_Click(object sender, EventArgs e) { AddTestActions(); pictureBox1.Invalidate(); } private void button2_Click(object sender, EventArgs e) { AddTestActions(); Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height); using (Graphics G = Graphics.FromImage(bmp)) Draw(G, actions); pictureBox1.Image = bmp; } void AddTestActions() { actions.Add(new DrawAction('L', Color.Blue, 3.3f)); actions[0].points.Add(new Point(23, 34)); actions[0].points.Add(new Point(23, 134)); actions.Add(new DrawAction('P', Color.Red, 1.3f)); actions[1].points.Add(new Point(11, 11)); actions[1].points.Add(new Point(55, 11)); actions[1].points.Add(new Point(55, 77)); actions[1].points.Add(new Point(11, 77)); }
两者的结果看起来一样:
尝试在函数之外创build位图来保存它,现在你正在做的方式是在函数完成之后处理位图元素。
你可以做一些类似的事情
Bitmap bmp = new Bitmap(pictureBox17.Width, pictureBox17.Height); private void draws() { if (bmp ==null) using (Graphics g = Graphics.FromImage(bmp)) { //define area do pictureBox17 e preenche a branco Brush brush = new SolidBrush(Color.White); Rectangle area = new Rectangle(0, 0, pictureBox17.Width, pictureBox17.Height); g.FillRectangle(brush, area); //desenha as linhas do rectangulo g.DrawLine(new Pen(Color.Black), esp, esp, esp, yWcorrigidoesp); } else { using (Graphics g = Graphics.FromImage(bmp)) { g.DrawLine(new Pen(Color.Black), esp, esp, esp, yWcorrigidoesp); } // some more lines } pictureBox17.Image = bmp; }
只是为了让你开始.. 🙂
或者,如果您使用此方法在不同时间绘制多个bmp,则可以将bmp传入绘图函数