更新绘图而不删除之前的绘图
Update a drawing without deleting the previous one
我在绘图方法中创建了这个
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;
}
它画的正是我想要的。但是想象一下,在这之后我想更新完全相同的绘图,添加几行,而不必重新绘制,这可能吗?显然我正在使用方法
draws();
然后我想补充一些东西,有什么提示吗?
尝试在函数外部创建位图以保存它,您现在的做法是在函数完成后处理位图元素。
然后你可以做类似
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 传递给 draw 函数
方法是创建一个 DrawAction
class 来保存你想要绘制的东西所需的所有数据:Point
数据,Pen
或 Brush
等
然后您创建并管理 List<DrawAction> drawActions
然后您有一个选择:
您要么在 PictureBox
的 Paint
事件中完成所有绘图 'live',要么 Panel
(或 任何 控制与 Paint
事件)通过循环列表..
..或者您将新操作 添加到您正在构建的 Bitmap Image
中 。
什么更好真的取决于:你是否希望进行动态绘图,比如通过用户操作?您想要 undo/redo 选项吗?然后实时绘图到控制面更适合。
或者待办事项列表是固定的还是从一组固定的数据中派生出来的,并且最终会保存到磁盘中。这听起来更像是将 绘制到 位图中。
两者也可以组合,也许可以收集一些动作,同时保留撤消选项(通过删除最后一个列表项)并提供应用 按钮将它们泵入位图中..
注意:绘图的关键是将绘图数据保存在列表中,以便您在需要时可以使用它再一次,展开和删除列表,甚至更改它:遍历所有操作并更改 Color
或 Width
或 LineStyle
将是一个简单的两行代码Pen
或稍微移动 Points
等等!
当您创建 DrawAction
class 时,如果您可以决定需要执行哪些操作,这会有所帮助。如果你不能,你仍然可以选择一个更扩展的 class,有足够的成员来使用 Graphics
class 提供的所有选项:Drawxx
,Fillxxx
, Pen
属性, Colors
甚至可以缩放..
对于初学者来说,一个类型,一个List<Point>
一个float PenWidth
和一个Color
就可以了..
这里有一个简单的例子 class,Paint
事件,添加一些测试动作的代码和 both
:
- 一个用于实时绘图和..
的按钮
- ..one 将操作应用于
PictureBox
. 的位图 Image
测试数据为一个Line
和一组Polylines
。
您应该通过定义一个 Enum
来开始改进它,其中包含您要使用的所有绘图动作类型!这将更好、更容易理解我编写的廉价字符类型 ;-) 类型可能包括 Rectangle, FilledRectangle, Ellipse, FilledEllipse, Line, Lines, Polygon, FilledPolygon, Text, Curve, Curves
等等。再加上一点额外的东西,你还可以使用图像、图形路径、样条曲线。其他数据可以控制 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));
}
两者的结果看起来一样:
Update 另一个可能更合适的设计是在 DrawAction class 中有一个 Draw (Graphics g)
方法。然后在 Paint 事件中这样做:foreach (DrawAction da in drawActionList) da.Draw(e.Graphics);
我在绘图方法中创建了这个
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;
}
它画的正是我想要的。但是想象一下,在这之后我想更新完全相同的绘图,添加几行,而不必重新绘制,这可能吗?显然我正在使用方法
draws();
然后我想补充一些东西,有什么提示吗?
尝试在函数外部创建位图以保存它,您现在的做法是在函数完成后处理位图元素。
然后你可以做类似
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 传递给 draw 函数
方法是创建一个 DrawAction
class 来保存你想要绘制的东西所需的所有数据:Point
数据,Pen
或 Brush
等
然后您创建并管理 List<DrawAction> drawActions
然后您有一个选择:
您要么在
PictureBox
的Paint
事件中完成所有绘图 'live',要么Panel
(或 任何 控制与Paint
事件)通过循环列表....或者您将新操作 添加到您正在构建的
Bitmap Image
中 。
什么更好真的取决于:你是否希望进行动态绘图,比如通过用户操作?您想要 undo/redo 选项吗?然后实时绘图到控制面更适合。
或者待办事项列表是固定的还是从一组固定的数据中派生出来的,并且最终会保存到磁盘中。这听起来更像是将 绘制到 位图中。
两者也可以组合,也许可以收集一些动作,同时保留撤消选项(通过删除最后一个列表项)并提供应用 按钮将它们泵入位图中..
注意:绘图的关键是将绘图数据保存在列表中,以便您在需要时可以使用它再一次,展开和删除列表,甚至更改它:遍历所有操作并更改 Color
或 Width
或 LineStyle
将是一个简单的两行代码Pen
或稍微移动 Points
等等!
当您创建 DrawAction
class 时,如果您可以决定需要执行哪些操作,这会有所帮助。如果你不能,你仍然可以选择一个更扩展的 class,有足够的成员来使用 Graphics
class 提供的所有选项:Drawxx
,Fillxxx
, Pen
属性, Colors
甚至可以缩放..
对于初学者来说,一个类型,一个List<Point>
一个float PenWidth
和一个Color
就可以了..
这里有一个简单的例子 class,Paint
事件,添加一些测试动作的代码和 both
:
- 一个用于实时绘图和.. 的按钮
- ..one 将操作应用于
PictureBox
. 的位图
Image
测试数据为一个Line
和一组Polylines
。
您应该通过定义一个 Enum
来开始改进它,其中包含您要使用的所有绘图动作类型!这将更好、更容易理解我编写的廉价字符类型 ;-) 类型可能包括 Rectangle, FilledRectangle, Ellipse, FilledEllipse, Line, Lines, Polygon, FilledPolygon, Text, Curve, Curves
等等。再加上一点额外的东西,你还可以使用图像、图形路径、样条曲线。其他数据可以控制 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));
}
两者的结果看起来一样:
Update 另一个可能更合适的设计是在 DrawAction class 中有一个 Draw (Graphics g)
方法。然后在 Paint 事件中这样做:foreach (DrawAction da in drawActionList) da.Draw(e.Graphics);