引言
经过前面两篇文章的准备,我们已经完成了对这个标记语言的构思和解析策略,那么接下来,就轮到渲染逻辑了。
大部分Markdown和其它用于富文本的标记语言的应用,都是讲原本的标记语言转为html格式,然后再由浏览器组件渲染。但是Tin不是,Tin(主体)完全依靠tkinter自身实现,因此在使用方面方便开发。
而且,据我所知,tkinter能够自动显示的富(超)文本,只有html,包括 tkhtmlview(html3文本框)、tkinterhtml(不好用,效果也不好)、cefPython(100M+)。如果tkinter要显示Markdown,必须将Markdown转为HTML。而且,TinEngine 只有不到 1M,因为引入了很多杂项但又必不可少,编译的时候杂项就很大了。
渲染顺序
说是渲染,实际上并不需要我们进行排版,只用把相对应标签的内容呈现出来就可以了。在tkinter的文本框中,完全有能力进行富文本渲染。但是首先,我们需要弄清楚顺序和逻辑。
顺序逻辑
首先应该是解析标签集,然后再到标签行,很简单,在前一篇文章已经解决了,并且还为渲染部分代码留出了位置。
如果忘记了前一篇文章最后一个代码片段,这里再一次给出:
self.pass_l=False
self.pass_u=[]#标签行列表
self.askyn_l=False
self.askyn_u=[]
self.tk_l=False
self.tk_u=[]
for i in units:#同上面的代码片段
#【正则匹配部分】
#...
#判断是否结束标签集
if obj in ['</-pass>','</-askyesno>','</tkinter>']:
if obj=='</-pass>':
self.pass_l=False
self.point_file(self.pass_u)#渲染容器内标签
self.pass_u=[]
continue
#其它标签集同理
#判断是否正在标签集,其它标签集同理
if self.pass_l==True:
self.pass_u.append(i)
continue
#【渲染部分】
#...
#判断是否开始标签集
if obj in ['<-pass->','<-askyesno->','<tkinter>']:
if obj=='<-pass->':
self.pass_l=True
continue
#其它标签集同理
标签集
无论如何,只要有标签集存在,那么就暂停每行都解析,等待标签集结束后,再将标签集的所有标签行内容进行渲染。这个步骤在上面的代码已经有了,也就是使用Tin渲染文本框的 point_file 功能。现在我们来处理正常的标签行用什么逻辑渲染。
关于 TinEngine.pyd,在本专题下下篇文章会开始提到。
标签行
为了处理不同名称的标签行,首先会想到 if-elif-else 语句,这样来处理不同名称的标签就十分简单了。这不是不可以,但是感觉不那么整齐。如果讲究规范或者是代码排版,可以先定义一个函数字典,每个标签名称对应的函数。具体如下:
#节省时间,这里只用 <title> 做栗子
#self.p_title 函数已经定义好,也就是具体怎么渲染<title>标签
self.obj_dict={'<title>':self.p_title}#...
#obj: 标签名称
#us: 标签参数列表
self.obj_dict[obj](us)
文本框外的功能
在Tin中,除了单纯靠文本框功能进行渲染,还有专门的gif显示框(对于动态显示gif,tkinter不能改变大小,PIL改变大小会失真)、询问框以及用画布实现的文本框内的组件。这些完全可以自己写出了。
在我的 tkinter实现 专栏中,就有对tkinter创新组件和使用的文章。
结语
还记得之前讲过,Tin标记语言不支持嵌套吗?而且还有一个问题,就是重复的、日常编辑比较复杂的标记文本,怎么化简?这两个问题会在下一篇文章用同一种方法解决。在下一篇文章后,将正式会用 TinEngine.pyd。
日常编辑比较复杂的标记文本,怎么化简?这两个问题会在下一篇文章用同一种方法解决。在下一篇文章后,将正式会用 TinEngine.pyd。