tkinter使用wpf控件

引言

wpf作为一种先进的Windows UI框架,有着丰富的控件与功能,以及超快的渲染速度。

在此之前,我已经实现了在tkinter中使用WinFroms控件,但是WinFroms更像是传统win32,而且wpf可以使用xaml设计界面。那么我们能否在tkinter中使用wpf控件呢?

答案是可以的。

因为wpf控件众多,将其一一绑定不太现实。因此本篇文章只实现允许在tkinter中使用wpf,然后由编写者自己在其中添加WPF控件。

为了方便编写,一个tkWPF只提供一个wpf控件,毕竟并不是要创建一个wpf窗口,我们只是希望使用其中几种控件。

当然,如果编写者在里面添加一个Window控件来显示xaml内容,那我也不强求。


提前申明

我们需要有wpf库的核心支持以及pythonnet。

程序需要在STA线程模式下运行。


可以显示wpf的tkinter控件

wpf嵌入WinFroms

这里,首先我们需要将wpf控件嵌入到WinFroms中,接下来的事就好办了。

先导入所需的东西:

import clr
clr.AddReference('System.Windows.Forms')
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")
clr.AddReference('WindowsFormsIntegration, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35')#?
clr.AddReference('System.Threading')
from clr import System
from System import Uri
from System.Windows.Controls import ContentControl,Button as wpfButton,MediaElement
from System.Windows.Forms.Integration import ElementHost
from System.Windows.Forms import Control
from System.Threading import Thread,ApartmentState,ThreadStart
from tkinter import Frame,Tk
from tkinter import ttk
import ctypes
user32=ctypes.windll.user32

创建类:

class tkWPF(Frame):
    """在tkinter中显示一个wpf控件"""

    def __init__(self,parent,width=500,height=500):
        Frame.__init__(self,parent,width=width,height=height)
        #...

创建WinFroms载体:

        wf=Control()#WinForm载体
        wf.Width=width
        wf.Height=height

创建wpf载体并嵌入WinFroms载体中:

        el=ElementHost()#WPF载体
        el.Width,el.Height=width,height
        wf.Controls.Add(el)
        el.Visible=True
        uc=ContentControl()#WPF控件
        el.Child=uc
        self.wf=wf
        self.el=el
        self.uc=uc

使用这个WinFroms控件

这个之前讲过,直接给代码。

        self.wfhwnd=int(str(self.wf.Handle))
        user32.SetParent(self.wfhwnd,self.winfo_id())
        user32.MoveWindow(self.wfhwnd,0,0,width,height,True)
        self.bind('<Configure>',self.__resize)
        
    def __resize(self,event):
        width=self.winfo_width()
        height=self.winfo_height()
        self.wf.Width,self.el.Width=width,width
        self.wf.Height,self.el.Height=height,height

创建一个wpf控件

这个过程由编写者决定,tkWPF提供一个control方法。

    def control(self,control):#确定新的wpf控件
        self.uc.AddChild(control)

这里ContentControl类只能使用一个wpf控件

完整类代码

class tkWPF(Frame):
    """在tkinter中显示一个wpf控件"""

    def __init__(self,parent,width=500,height=500):
        Frame.__init__(self,parent,width=width,height=height)
        wf=Control()#WinForm载体
        wf.Width=width
        wf.Height=height
        el=ElementHost()#WPF载体
        el.Width,el.Height=width,height
        wf.Controls.Add(el)
        el.Visible=True
        uc=ContentControl()#WPF控件
        el.Child=uc
        self.wf=wf
        self.el=el
        self.uc=uc
        self.wfhwnd=int(str(self.wf.Handle))
        user32.SetParent(self.wfhwnd,self.winfo_id())
        user32.MoveWindow(self.wfhwnd,0,0,width,height,True)
        self.bind('<Configure>',self.__resize)

    def __resize(self,event):
        width=self.winfo_width()
        height=self.winfo_height()
        self.wf.Width,self.el.Width=width,width
        self.wf.Height,self.el.Height=height,height

    def control(self,control):#确定新的wpf控件
        self.uc.AddChild(control)

简单示例

这里,我们将同时使用wpf的按钮和ttk的按钮。这里的wpf按钮大小随tkWPF控件的改变而改变。

def STAMain():
    global media
    try:
        a=Tk()
        a.geometry('500x500')
        ttk.Button(a,text='播放',command=play).pack()
        f=tkWPF(a)
        f.pack(fill='both',expand=True)

        btn=wpfButton()
        btn.Content='wpf button'
        f.control(btn)

        a.mainloop()
    except Exception as err:
        print(err)
 
def main():
    t = Thread(ThreadStart(STAMain))
    t.ApartmentState = ApartmentState.STA
    t.Start()
    t.Join()
 
if __name__ == "__main__":
    main()

一定要使用STA线程。

try语句中的第三段代码块就是确定显示的wpf控件是什么。

效果如下:

在这里插入图片描述


结语

wow,tkinter又有了一个十分强大的功能。

有了wpf,tkinter可以做很多事,比如播放常见格式视频(MPEG-4)等。通常tkinter播放视频还需要OpenCV、PIL这些杂七杂八的东西,效果还很不好。现在tkinter只靠pythonnet(以及wpf核心支持)就可以播放有声视频以及音频。下面是一个十分简单的示例:

在这里插入图片描述

tkinter正在变得更强大,爱好者团队也更多。

🔆tkinter创新🔆

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值