开发需求中需要实现一个压力分布的热力图,我在WPF中使用的图表组件是ScottPlot,想实现类似于等高线那种的热力分布图,查遍了所有的文档,都没能找到一个实现方案,于是想从python或者web的图表库中入手,使用ECharts应该也可以实现,但是需要在程序中嵌入一个Web Browser,于是想先研究一下使用python的方法,查阅了很久的资料后,发现了一个github上一个绝配的demo,这里也非常感谢这位大佬,github链接放在下面:
chickenservice/matplotlib.net: A wrapper to embed interactive matplotlib in WPF applications (github.com)
但是呢,在将这个demo集成到我的项目里时,也遇到了很多的问题,这里记录一下,可供参考。
首先,我直接将demo的代码clone到本地执行,进行测试,这里需要注意的是,作者在编写这个wrapper的时候,在C#中以及对fig, ax = plt.subplots()
进行了封装,在我们的python代码中,不需要出现fig
和ax
,可以直接使用,但是需要以闭包的形式作为函数参数才传递到需要使用fig和ax
的地方。举个例子:
1 | import numpy as np |
在作者的这个示例代码中,我们可以看到是没有对fig
和ax
进行定义的,而是直接作为参数传递进入了init
函数和FuncAnimation
中,且这里呢需要将_update
函数作为FuncAnimation
的参数进行传递,所以需要以闭包的形式获得_update
。总之,我们首先需要将我们自己的代码修改层类似demo中的代码的这种形式,才能够在作者的程序中运行python代码,当然这里条件是我也需要使用FuncAnimation
这个功能,如果不使用这个功能可能不需要这么麻烦。
其次,作者使用MplPanel.cs
和NetMplAdapter.cs
封装了自定义组件MplPanel
这样我们可以直接在我们的xmal
文件中,去使用这个组件,并且可以直接通过这个组件对象来进行python代码的调用,然后将可视化的图表直接显示在组件中。
下面讲一下将demo中的代码迁移到我自己的项目中,首先将所有的代码都先迁移到自己的项目中,并全部修改namespace
,由于作者使用的是.net7
框架,如果是使用.net framework
框架的可能需要修改一些代码,比如其中的using
的使用,可以使用ChatGPT
去问一下,比较好解决。其次有两个文件,一个是backend_wpfagg.py
,一个是appsettings.json
,这两个文件前者是matplotlib
的一个wpf的backend
,后者是指定python路径的配置文件,这两个文件只放到项目目录下是没用的,需要放到编译出的可执行文件的目录下,可以自行手动复制进去,也可以配置一下csproj
文件,在编译的时候自动复制进去。这里可以参考demo的csproj
文件:
1 | <Project Sdk="Microsoft.NET.Sdk"> |
以及backend_wpfagg.py
中的代码为:
1 | """ |
appsettings.json
中的代码为,这里是我自己的,仅供参考:
1 | { |
这里指定的python路径不能是python embed的,目前我也还不知道为什么,如果使用python embed的环境,会出现软件运行就结束的情况,没有任何报错,使用try-catch
也捕获不到任何的异常,这里我使用的是Miniconda
创建的虚拟环境,而且注意,python的版本要在pythonnet
这个库的支持范围内。
然后重点来了,这里在你自己的项目中直接运行可能会出现报错找不到Matplotlib这个库
,但是请注意,这里的Matploblib
非彼matplotlib
,这里的Matploblib
是backend_wpfagg.py
中的这行代码:
1 | from Matplotlib.Net import NetMplAdapter |
所以在这里,务必将这里的Matplotlib.Net
修改成你自己的项目名称,否则这个错误根本找不到解决方法。