WPF异步高效绘制过万级别的矩形图形矢量图,无限放大缩小,显示效果极佳

WPF异步高效绘制过万级别的矩形图形矢量图,无限放大缩小,显示效果极佳,先看效果如下:
在这里插入图片描述
在这里插入图片描述
想在WPF上绘制图形,有哪些方式?

1.通过Canvas静态绘图方法,例如:

<Canvas>
    <Ellipse Width="50" Height="50" Fill="Blue" Canvas.Left="10" Canvas.Top="10"/>
    <Rectangle Width="80" Height="40" Fill="Red" Canvas.Left="50" Canvas.Top="50"/>
</Canvas>

2.DrawingContext进行绘图,例如:

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);

    // 创建一个画刷和画笔
    SolidColorBrush brush = new SolidColorBrush(Colors.Green);
    Pen pen = new Pen(Brushes.Black, 2);

    // 绘制一个矩形
    drawingContext.DrawRectangle(brush, pen, new Rect(10, 10, 100, 50));
}

3.使用DrawingVisual进行低级别的绘图

DrawingVisual是一个轻量级的可视化对象,允许你在低级别上执行绘图。通过重写OnRender方法,你可以使用DrawingContext在DrawingVisual上进行绘图。

例如:

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);

    using (DrawingContext dc = drawingContext.RenderOpen())
    {
        // 在DrawingVisual上进行绘图
        dc.DrawEllipse(Brushes.Blue, new Pen(Brushes.Black, 2), new Point(50, 50), 30, 30);
    }
}

4.使用graphics绘制Image流可以直接绑定到界面

但是如果要考率绘制大批量图形,我们就要性能和内存等多个方面考虑了,否则绘制1w的矩形需要1分钟,哪个客户也接受不了啊。

我们考虑这些方面:

  • 1.使用UI 虚拟化控件: 如果你有过万级别的矩形,不要一次性全部绘制。考虑采用虚拟化的方式,只在当前视图区域内绘制可见的矩形。这可以通过一些控件如VirtualizingStackPanel或者自定义的虚拟化机制来实现。
  • 2.使用独立的绘制线程: 考虑在一个独立的绘制线程中进行绘制操作,以避免对UI主线程的影响。这样可以更好地控制绘制操作的调度和频率。
  • 3.多线程异步绘制 将绘制操作异步化,可以避免UI主线程阻塞。使用Task或async/await模式来在后台线程进行绘制操作,然后在UI线程更新视图。
  • 4.自定义UIElement: 如果使用WPF,可以考虑创建自定义的UIElement,通过重写OnRender方法实现高效的绘制。确保只在需要更新时进行绘制。
  • 5.可以使用Freezable类来冻结Pen对象,这个对提高性能有非常明显的对比,最后我在这里做个测评

实现过程:

XAML代码

<Window x:Class="WpfAppTest.shiliangTest"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfAppTest" PreviewMouseWheel="Window_PreviewMouseWheel"
        mc:Ignorable="d"
        Title="shiliangTest" Height="800" Width="1000">
    <Grid>
        <Canvas x:Name="DrawingContainer" Width="800" Height="800" Panel.ZIndex="1" />

    </Grid>
</Window>

后台代码:

   public class VisualHost1 : FrameworkElement
   {
       private readonly DrawingVisual _drawingVisual;

       public VisualHost1()
       {
           _drawingVisual = new DrawingVisual();
       }

       public DrawingContext RenderOpen()
       {
           return _drawingVisual.RenderOpen();
       }

       protected override void OnRender(DrawingContext drawingContext)
       {
           base.OnRender(drawingContext);
           drawingContext.DrawDrawing(_drawingVisual.Drawing);
       }
   }
  public VisualHost1 _visualHost;
  double scale;
  public shiliangTest()
  {
      InitializeComponent();

      _visualHost = new VisualHost1();
      DrawingContainer.Children.Add(_visualHost);

      double canvasWidth = DrawingContainer.Width;
      double canvasHeight = DrawingContainer.Height;
      //double canvasWidth = 3000;
      //double canvasHeight = 3000;
      new SelectBoxRect(DrawingContainer);

      using (new PerformanceCounter("ghfgh"))
      {
          DrawRectangles1(canvasWidth, canvasHeight);
      }
      scale = 1;
  }

private void Window_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {

            if (Keyboard.IsKeyDown(Key.LeftCtrl))
            {
                if (e.Delta < 0)
                {
                    scale -= 0.01;
                }
                else
                {
                    scale += 0.01;
                }
                // scale += (double)e.Delta / 35000;
                ScaleTransform transfrom = new ScaleTransform();
                transfrom.ScaleX = transfrom.ScaleY = scale;
                this.DrawingContainer.RenderTransform = transfrom;
            }
}  

  private Pen CreateAndFreezePen()
  {
      // 创建Pen
      Pen pen = new Pen(Brushes.Black, 1);

      // 冻结Pen
      if (pen.CanFreeze)
      {
          pen.Freeze();
      }

      return pen;
  }

  private void DrawRectangles1(double canvasWidth, double canvasHeight)
  {
      int rows = 100; // 纵向矩形数量
      int columns = 100; // 横向矩形数量


      using (DrawingContext drawingContext = _visualHost.RenderOpen())
      {

          double rectangleWidth = canvasWidth / columns;
          double rectangleHeight = canvasHeight / rows;

          var pen = CreateAndFreezePen();
          for (int i = 0; i < columns; i++)
          {
              for (int j = 0; j < rows; j++)
              {
                  double x = i * rectangleWidth;
                  double y = j * rectangleHeight;

                  // 创建矩形几何图形
                  Rect rectangleRect = new Rect(new Point(x, y), new Size(rectangleWidth, rectangleHeight));
                  Geometry rectangleGeometry = new RectangleGeometry(rectangleRect);

                  // 绘制矩形
                  //drawingContext.DrawGeometry(Brushes.Blue, new Pen(Brushes.Black, 1), rectangleGeometry);
                  drawingContext.DrawGeometry(Brushes.Blue, pen, rectangleGeometry);

              }
          }
      }
  }
        

对比是否冻结Pen的结果

这是未冻结的耗时
在这里插入图片描述

这是冻结后的耗时
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/330584.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从前端角度浅谈性能 | 京东物流技术团队(转载)

1 前言 自网站诞生以来&#xff0c;页面白屏时间、用户交互的响应速度等一直都是开发者关心的问题&#xff0c;这直接影响了一个网站能否为用户的浏览提供舒适的服务&#xff0c;而这种舒适度&#xff0c;直接关系着对用户的吸引力&#xff0c;毕竟谁都不能忍受一个页面长达10秒…

linux-nfc neard 编译、安装与运行

项目github地址&#xff1a; https://github.com/linux-nfc/neard git clone地址&#xff1a; https://github.com/linux-nfc/neard.git 1.安装依赖库 clone完源码切换到目录neard里。这个项目需要依赖一下库&#xff1a; - GCC compiler - D-Bus library - GLib library …

muduo网络库剖析——监听者EpollPoller类

muduo网络库剖析——监听者EpollPoller类 前情从muduo到my_muduo 概要epoll原理解析epoll提供的接口epoll的触发模式epoll实现多路复用 框架与细节成员函数使用方法 源码结尾 前情 从muduo到my_muduo 作为一个宏大的、功能健全的muduo库&#xff0c;考虑的肯定是众多情况是否…

Jenkins-Pipeline

Pipeline 1 安装插件 2 新建一个 Pipline 工程 3 配置Pipeline 脚本 agent的使用可以参考这个文档 pipeline {agent anystages {stage(Build) { steps {echo Building project...}}stage(Test) { steps {echo Testing project...}}stage(Deploy) { steps {echo Deploying …

STL之vector容器的介绍与模拟实现

STL之vector容器的介绍与模拟实现 1. vector简介2. vector容器使用2.1vectord 定义2.2 vector iterator 的使用2.3 vector 空间增长问题2.4 注意事项 3. vector功能模拟实现3.1 架构搭建3.2 空间控制板块3.3 迭代器3.4 增加/删除数据3.5 运算符重载3.6构造/析构 4. 整体代码 所…

vscode mysql cmake windows 常见问题和推荐文章

1.在windows中安装mingw64和cmake&#xff08;可查一下网上的安装教程&#xff09;&#xff0c;配置环境变量 2.在vscode中用CMake构建项目的时候&#xff0c;可能会出现这样的问题:“The C compiler identification is unknownn...”,可参考这篇博客 在windows下使用Vscode用…

Java基础面试题(四)

Java基础面试题&#xff08;四&#xff09; 文章目录 Java基础面试题&#xff08;四&#xff09;Oracle JDK vs OpenJDKJava 和 C 的区别? 文章来自Java Guide 用于学习如有侵权&#xff0c;立即删除 Oracle JDK vs OpenJDK 可能在看这个问题之前很多人和我一样并没有接触和使…

基于springboot+vue的图书个性化推荐系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

1. 安装Git

01. 安装Git 最早Git是在Linux上开发的&#xff0c;很长一段时间内&#xff0c;Git也只能在Linux和Unix系统上跑。不过&#xff0c;慢慢地有人把它移植到了Windows上。现在&#xff0c;Git可以在Linux、Unix、Mac和Windows这几大平台上正常运行了。 要使用Git&#xff0c;第一…

【C++入门到精通】智能指针 auto_ptr、unique_ptr简介及C++模拟实现 [ C++入门 ]

阅读导航 引言一、std::auto_ptr1. 简介2. 使用示例3. C模拟实现 二、std::unique_ptr1. 简介2. 使用示例3. C模拟实现 温馨提示 引言 在 C 中&#xff0c;智能指针是一种非常重要的概念&#xff0c;它能够帮助我们自动管理动态分配的内存&#xff0c;避免出现内存泄漏等问题。…

靶机-Billu_b0x root 123456

查找靶机IP nmap查看开放端口22&#xff0c;80 目录扫描 查看网站&#xff0c;典型注入 phpmy 果然是登陆界面&#xff0c;不过不知道账户及密码 in.php php的配置信息&#xff0c;可以看看 add.php 上传文件目录&#xff0c;可以上传&#xff0c;不过没有回显 …

C# ObjectArx 绘制表格并设置单元格合并

第一行默认是标题&#xff0c;可设置行【RowType】进行设置类型 Document doc Application.DocumentManager.MdiActiveDocument;using (Transaction tr doc.TransactionManager.StartOpenCloseTransaction()){BlockTable bt tr.GetObject(doc.Database.BlockTableId, OpenMo…

UE4 添加按键输入事件 并在蓝图中使用按键输入节点

绑定按键 选择Edit/ProjectSettings/Engine/Input 在bindings中可以选择添加ActionMappings或则AxisMappings ActionMappings:按键事件&#xff0c;有按下和抬起两个事件&#xff0c;需要分别用两个键触发AxisMappings:输入事件&#xff0c;返回值为float&#xff0c;对于键盘…

Rust之构建命令行程序(三):重构改进模块化和错误处理

开发环境 Windows 10Rust 1.74.1 VS Code 1.85.1 项目工程 这次创建了新的工程minigrep. 重构改进模块化和错误处理 为了改进我们的程序&#xff0c;我们将修复与程序结构及其处理潜在错误的方式有关的四个问题。首先&#xff0c;我们的main函数现在执行两项任务:解析参数和…

一文了解Servlet

文章目录 1、什么是Servlet2、Servlet快速入门3、Servlet生命周期4、Servlet体系结构5、urlPatern配置6、XML编写Servlet 1、什么是Servlet Servlet是Java提供的一门动态web资源开发技术Servlet是JavaEE规范之一&#xff0c;其实就是一个接口&#xff0c;将来我们需要定义Serv…

Apache JMeter 5.6.3压力测试步骤详解

Apache JMeter 5.6.3压力测试步骤详解 压力测试简介软件测试概述性能测试性能测试指标性能指标推算web资源公式 1. 安装 Jmeter2. 创建测试任务2.1 创建线程组2.2 创建 HTTP 请求2.3 添加HTTP消息头管理器 3.添加查看结果监听器4. 执行测试5. 查看结果6. 非GUI模式测试7. 使用c…

CSS||Emmet语法

1、简介 ​ Emmet语法的前身是Zen coding,它使用缩写,来提高html/css的编写速度, Vscode内部已经集成该语法。 ​ 快速生成HTML结构语法 ​ 快速生成CSS样式语法 2、快速生成HTML结构语法 生成标签 直接输入标签名 按tab键即可 比如 div 然后tab 键&#xff0c; 就可以生成 <…

CSS 设置背景图片

文章目录 设置背景颜色设置背景图片背景图片偏移量计算原点背景图片尺寸设置背景图片位置设置背景图片重复方式设置背景范围设置背景图片是否跟随元素移动测试背景图片 本文概念部分参考&#xff1a;CSS背景background设置 设置背景颜色 background-color 设置背景颜色 设置…

UE5 独立程序的网络TCP/UDP服务器与客户端基础流程

引擎源码版&#xff0c;复制\Engine\Source\Programs\路径下的BlankProgram空项目示例。 重命名BlankProgram&#xff0c;例如CustomTcpProgram&#xff0c;并修改项目名称。 修改.Build.cs内容 修改Target.cs内容 修改Private文件夹内.h.cpp文件名并修改.cpp内容 刷新引擎 …

联想模拟器抓包

联想模拟器抓包 下载抓包工具配置代理并启动模拟器配置代理返回reqable查看抓包数据 下载抓包工具 reqable 配置代理并启动 模拟器配置代理 返回reqable查看抓包数据