通过 PythonNet 使用 WPF

我在前面的这篇文章里,介绍了 Python for .NET 的编译和基本使用。当时只是简单地测试了用其调用 .NET 的库的功能,并没有更加深入。这两天的一个设计,需要快速开发一个简单的 GUI 程序来验证,在找了一堆 Python GUI 库后,突然灵光一动,为什么不使用 Python for .NET 来调用 WPF 呢?

说干就干,网上搜索一番,发觉这方面的资料并不多。于是查看了下 PythonNet 的源代码,里面的 demo 目录里倒是有几个 GUI 的示范程序,不过都是用 Windows Form 技术,而并不是 WPF。对于 GUI 框架,说实在的,我还只用过 MFC,但最近也稍微看了看 WPF,不过对于 Windows Form 这个可以说将被 WPF 代替的技术我是一点都不熟。

于是只有自己摸索。首先遇到的问题,就是如何引用 PresentationFramework 和 PresentationCore 这两个程序集。这两个程序集是加载到 GAC 里的,我尝试了很久,才发现需要用如下的方式进行引用:

import clr
clr.AddReference("PresentationFramework.Classic, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
clr.AddReference("PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")

from System.Windows import Application
from System.Windows import Window
from System.Threading import Thread
from System.Threading import ApartmentState
from System.Threading import ThreadStart

遇到的第二个问题是关于 STAThread 的。WPF GUI 组件要求都在 STA 线程里创建。这个在 C# 里通过一个 Attribute 就可以搞定,可是用 PythonNet 该怎么实现呢?琢磨的结果是,从主线程里创建一个新的线程,将其设定为 STA 线程,所有工作都在 STA 线程里执行,主线程仅简单地等待 STA 线程的退出。

下面是一段完整的代码,弹出一个 WPF 的 Window:

import clr
clr.AddReference("PresentationFramework.Classic, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
clr.AddReference("PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")

from System.Windows import Application
from System.Windows import Window
from System.Threading import Thread
from System.Threading import ApartmentState
from System.Threading import ThreadStart

def AppStartUp(sender, e):
    mainWnd = Window()
    mainWnd.Title = "WPF From PythonNet!"
    mainWnd.Show()

def STAMain():
    app = Application()
    app.Startup += AppStartUp
    app.Run()

def main():
    t = Thread(ThreadStart(STAMain))
    t.ApartmentState = ApartmentState.STA
    t.Start()
    t.Join()

if __name__ == "__main__":
    main()
哈哈,终于从 Python 中调用了 WPF 的窗口了。有了这个基础,扩充出复杂的 UI 也不是问题,而且 Python 语言的灵活性使得原型开发加快了不少。不过还有一些细节问题,比如怎么处理 XAML 等,还有待进一步研究。



你可能感兴趣的:(import,wpf,python,.net,windows)