wpf绘图性能分析

2022-10-31 12:01:47 浏览数 (1)

canvas绘制控件

使用canvas启动绘制label控件,10000个需要2-3s的时间

代码语言:javascript复制
for (int i = 0; i < 10000; i  )
 {
       canvas.Children.Add(new Label() { Content = i.ToString(), BorderBrush = Brushes.Black, BorderThickness = new Thickness(3), FontSize = 40 });
       Canvas.SetLeft(canvas.Children[canvas.Children.Count - 1], rd.Next(0, (int)canvas.ActualWidth - 100));
       Canvas.SetTop(canvas.Children[canvas.Children.Count - 1], rd.Next(0, (int)canvas.ActualHeight - 100));
   }

drawvisual绘制

使用drawvisual绘制,需要重载封装控件

代码语言:javascript复制
public class DrawVisualShow :FrameworkElement
        {
            Random rd = new Random();
            readonly VisualCollection _children;
            public DrawVisualShow(Window win)
            {
                _children = new VisualCollection(this);
                for (int i = 0; i < 10000; i  )
                {
                    Point pt = new Point((double)rd.Next(0, (int)win.ActualWidth - 100),
                        (double)rd.Next(0, (int)win.ActualHeight - 100));
                    DrawingVisual dv = new DrawingVisual();
                    DrawingContext dc = dv.RenderOpen();
                    dc.DrawRectangle(Brushes.Green, new Pen(Brushes.Black, 3), new Rect(pt.X, pt.Y, 20, 10));
                    dc.DrawText(new FormattedText(i.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Arial"), 10, Brushes.Red), new Point(pt.X   10, pt.Y   5));
                    dc.Close();
                    _children.Add(dv);
                }
            }
            protected override int VisualChildrenCount
            {
                get { return _children.Count; }
            }
            protected override Visual GetVisualChild(int index)
            {
                return _children[index];
            }
        }

在window中添加

AddChild(new DrawVisualShow(this));

添加10000个图形节点大约1-2s,10w个图形需要5-6s,还是很慢,绘制的时候会调用gpu,但效率没提升多少,使用drawvisual还有一个问题是内存很高。

wpf使用gdi

定义属性成员

代码语言:javascript复制
System.Drawing.Image _bitmap;
public BitmapImage BitmapSource
{
    get
    {
        MemoryStream _ms = new MemoryStream();
        _bitmap.Save(_ms, ImageFormat.Png);
        BitmapImage bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.StreamSource = _ms;
        bitmapImage.EndInit();
        return bitmapImage;
    }
}

调用gdi 绘制,10000个1-2s,10w个3-4s

代码语言:javascript复制
_bitmap = new System.Drawing.Bitmap((int)ActualWidth, (int)ActualHeight);
using (Graphics g = Graphics.FromImage(_bitmap)) {
   for (int i = 0; i < 100000; i  )
   {
       System.Windows.Point pt = new System.Windows.Point((double)rd.Next(0, (int)ActualWidth - 100),
           (double)rd.Next(0, (int)ActualHeight - 100));
       System.Drawing.Rectangle rt =new System.Drawing.Rectangle((int)pt.X,(int)pt.Y,20,10);
       g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Black, 3), rt);
       g.DrawString(i.ToString(), new Font("Arial", 15), System.Drawing.Brushes.Black, rt, new StringFormat()
       { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
   }
   image.Source = BitmapSource;
}

绘图框架在选取前,最好做个简单的性能测试,坑太多注意避坑。 wpf使用UIElement绘制,通过事件响应机制绘制,事件响应有很多坑

wpf中的一些坑

wpf是c#中快速开发ui的框架,你面有很多坑汇总一下

  • FrameworkElement的parent获取不到父节点

wpf有显示树和逻辑树结构,使用VisualTreeHelper.GetParent可以获取parent获取不到的父节点

  • mousemove不连续,mouseup事件丢失(mousemove状态监测)

mousemove事件不连续,需要CaptureMouse、ReleaseMouseCapture 个人经历,在做拖拽矩形时,位置计算的点在left、top位置,没有在矩形中心区域计算错误导致,拖拉异常

  • dragenter、dragleave事件错误,没找到原因,只能尽量避免使用
  • usercontorl不响应keydown的问题

windows窗口中添加keydown,传递到usercontrol中来

0 人点赞