引言
rtf文件是最经典的富文本格式文件,可以显示丰富的文本内容,同时还可以附带多种图片、附件以及加载项。虽然rtf相比于HTML和docx等文件并不是很有竞争力,但是因为其编辑方便,显示样式足够丰富,常被用于显示用户条例、软件文档、特殊输出信息显示等方面。
所以,在tkinter应用中显示*.rtf文件,我认为很有必要。
但是,tkinter无论从顶层还是底层来看,都没有办法显示*.rtf富文本格式的功能。但是,参照隔壁的WinForms,我们或许可以嵌入一个RichTextBox
。
容我赞扬一番
Python的一个第三方库:pythonnet
是真的香,其也被引用为clr
,可以调用Windows SDK。
所以无论是图像处理、GUI控件和线程等,均可以使用Windows提供的API。
我们需要使用pythonnet
,使用pip下载安装,而且clr.pyd
体积很小。
创建类
先引用一波。
from tkinter import Tk,Frame
from webbrowser import open as webopen
import ctypes
user32=ctypes.windll.user32
import clr
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
clr.AddReference('System')
from System.Windows.Forms import RichTextBox
from System.Drawing import Font
from System import String,Single
这个很简单了(在这个专栏里,我们已经创建超多自定义控件类了)。
class TkRichtext(Frame):
'''显示*.rtf文件的tkinter富文本组件'''
def __init__(self,master,width,height):
Frame.__init__(self,master,width=width,height=height)
font=Font(String('微软雅黑'),Single(13))
self.rt=RichTextBox()
self.rt.Font=font
self.rthwnd=int(str(self.rt.Handle))
user32.SetParent(self.rthwnd,self.winfo_id())
user32.MoveWindow(self.rthwnd,0,0,width,height,True)
匹配Frame父组件大小
为了让它看起来更像是一个tkinter控件,我们需要为其自动适配大小。
class TkRichtext(Frame):
'''显示*.rtf文件的tkinter富文本组件'''
def __init__(self,master,width,height):
#...
self.bind('<Configure>',self.__resize)
def __resize(self,event):
self.rt.Width=self.winfo_width()
self.rt.Height=self.winfo_height()
打开文件中的超链接
其实我们发现,原来富文本框的超链接点击仅仅是一个空事件,需要我们自己绑定对超链接点击的处理方法。这里,我们直接使用浏览器打开。
class TkRichtext(Frame):
'''显示*.rtf文件的tkinter富文本组件'''
def __init__(self,master,width,height):
#...
self.__bind_event()
def __bind_event(self):
self.rt.LinkClicked+=self.__openlink
def __openlink(self,sender,e):#点击链接
webopen(e.LinkText)
这里之所以使用
__bind_event
来统一管理事件绑定,就是因为我还没来得及深入查看该组件的所有方法和事件,所以预留这一种途径。
载入rtf文件
因为目前我还没有深入了解这个WinForms组件,因此我只能给出这一个本地化函数了。
def loadfile(self,path):
#载入*.rtf文件
self.rt.LoadFile(path)
完整代码
from tkinter import Tk,Frame
from webbrowser import open as webopen
import ctypes
user32=ctypes.windll.user32
import clr
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
clr.AddReference('System')
from System.Windows.Forms import RichTextBox
from System.Drawing import Font
from System import String,Single
class TkRichtext(Frame):
'''显示*.rtf文件的tkinter富文本组件'''
def __init__(self,master,width,height):
Frame.__init__(self,master,width=width,height=height)
font=Font(String('微软雅黑'),Single(13))
self.rt=RichTextBox()
self.rt.Font=font
self.rthwnd=int(str(self.rt.Handle))
user32.SetParent(self.rthwnd,self.winfo_id())
user32.MoveWindow(self.rthwnd,0,0,width,height,True)
self.bind('<Configure>',self.__resize)
self.__bind_event()
def __bind_event(self):
self.rt.LinkClicked+=self.__openlink
def __openlink(self,sender,e):#点击链接
webopen(e.LinkText)
def __resize(self,event):
self.rt.Width=self.winfo_width()
self.rt.Height=self.winfo_height()
def loadfile(self,path):
#载入*.rtf文件
self.rt.LoadFile(path)
def test():
a=Tk()
a.geometry('600x600+5+5')
rt=TkRichtext(a,500,500)
rt.pack(fill='both',expand='True')
rt.loadfile(r"E:\Py软件\Tin文件\软件说明.rtf")
#这是我自己的文件,大家以自己的测试文件的路径为准
a.mainloop()
if __name__=='__main__':
test()
效果
偷懒
当然,这个模块已经上传至PYPI了,你们可以通过pip安装tkrichtext
库。
结语
事实上,我发现结合Windows SDK,tkinter会有非常多的新玩法,大家可以尽情尝试和探索!
☀tkinter创新☀