我遇到了一个关于GDI +效率的问题。 有几个变量和方法 如下: 1.Points,如A(代表一个坐标点,如X Y Z),B,C,D,E等。
2名为Cmd1的列表,用于按线程添加点
3.Paint方法,在此方法中,连接到线
的点集4.Thread不断添加新的点,如F,G,H,I,J等。
在Paint Method中,我使用g.DrawLine()链接a和b,c,d,e。 在线程中,当我添加新点时,我将调用invalid来刷新组件。 所以我的问题是,积分变得越来越多,我怎样才能保持高效率,并重新绘制,
不要从重点画线开始。
Sub DrawGLines2(g As Graphics)
g.SmoothingMode = SmoothingMode.HighSpeed
Dim Pen As New Pen(Brushes.White)
Dim i As Int32
'Dim c As Int32
Dim preCmd1 As Cmd1
Try
For Each cmd As Cmd1 In Cmd1s
Dim pfs() As PointF = cmd.PointFs.ToArray
If preCmd1 IsNot Nothing Then
g.DrawLine(Pen, cmd.PointFs(0), preCmd1.PointFs(0))
End If
preCmd1 = cmd
End If
Next
Catch ex As Exception
Debug.Print(ex.Message)
End Try
End Sub
Private Sub Sheet_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
If Me.Cmd1s.Count>0 Then
DrawGLines2(e.Graphics)
End If
End Sub
Public Sub AddPoint(x As Double, y As Double, z As Double, Optional G As Int32 = -1)
Dim cmd1 As DrvSimu.Cmd1 = Nothing
If cmd1 Is Nothing Then
cmd1 = New DrvSimu.Cmd1
Me.Cmd1s.Add(cmd1)
End If
Dim pf3d As New PointF3D(x, y, z)
cmd1.PointF3Ds.Add(pf3d)
Me.Invalidate()
End Sub
线程将调用AddPoint添加a,b,c,d,e点,并使用无效方法刷新,当我调用invalid时," For Each cmd As Cmd1 In Cmd1s"对于每一个都将从A点开始,所以当点变得越来越多时,我怎样才能保持高效率,并且重绘,不要从A点开始重新绘制线条
答案 0 :(得分:1)
这取决于你究竟想做什么。
一种可能性是您目前正在使用的那种。在每个无效时,您重绘所有行。根据绘图质量和cpu,您可以绘制更多或更少的行,但应该可以每毫秒绘制至少10行。
如果您只添加线条并且不需要删除或修改它们,您还可以将所有线条绘制到位图,并且无效时您只能将该图像绘制到屏幕上。通过这种方式,您只需要在添加图片时将新线条绘制到图片中。此方法的问题在于,如果要缩放或平移区域,或者如果要删除线条,则仍需要完全重绘。
作为起点,请参阅Graphics.FromImage(...)方法。 使用Pixelformat Format32bppARGB获得最佳性能。
编辑:
public partial class LineForm : Form
{
private Bitmap lineBitmap = null;
private List<Tuple<PointF,PointF>> lines = new List<Tuple<PointF,PointF>>();
private List<Tuple<PointF,PointF>> newLines = new List<Tuple<PointF,PointF>>();
// must be set if you remove line, pan or zoom the view and if you resize the form.
private bool redrawAll = false;
public LineForm()
{
this.Paint += new System.Windows.Forms.PaintEventHandler(this.OnPaint);
this.Resize += new System.EventHandler(this.OnResize);
}
private void OnResize(object sender, EventArgs e)
{
if (this.lineBitmap!= null)
{
this.lineBitmap.Dispose();
}
if (this.Width <= 0 || this.Height <= 0)
{
return;
}
this.lineBitmap = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppPArgb);
this.redrawAll = true;
}
private void OnPaint(object sender, PaintEventArgs e)
{
Graphics lineGfx = Graphics.FromImage(this.lineBitmap);
// Settings for best drawing Performance. Must be adjusted for better quality
lineGfx.CompositingQuality = CompositingQuality.HighSpeed;
lineGfx.InterpolationMode = InterpolationMode.NearestNeighbor;
lineGfx.SmoothingMode = SmoothingMode.None;
lineGfx.PixelOffsetMode = PixelOffsetMode.None;
lineGfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
lineGfx.CompositingMode = CompositingMode.SourceCopy;
// Only clear the Image and draw all lines if necessary
if(this.redrawAll)
{
lineGfx.Clear(Color.Transparent);
foreach(Tuple<PointF,PointF> line in this.lines)
{
lineGfx.DrawLine(Pens.Black, line.Item1, line.Item2);
}
}
// Draw the new Lines to the Bitmap and store them to lines list
foreach(Tuple<PointF,PointF> newline in this.newLines)
{
lineGfx.DrawLine(Pens.Black, newline.Item1, newline.Item2);
tihs.lines.Add(newLine);
}
// Clear the newLines List as the liones are added to the lines List now.
this.newLines.Clear();
// Draw the Bitmap to the screen
e.Graphics.DrawImageUnscaled(this.lineBitmap,0,0);
}
private void AddLine(PointF p1, PointF p2)
{
this.newLines.Add(new Tuple<PointF,PointF>(p1,p2));
// Invalidate the view => OnPaint Event is raised;
this.Invalidate();
}
}
注意:我还没有为List操作添加任何锁定机制。为了防止在使用它们时更改列表,您应该添加一些锁。