@TOC
前言
本文只作为笔记记录。
“tkinter.Text是仅次于Canvas的高丰富自由度的控件”,这句话在旧版TinML实现笔记中就写道。
这两个控件的具体讲解当然不是本文的重点,但是得知道,tkinter中的画布自由度绝对高于文本框,许多文本框实现不了的功能,可以交给画布实现。
关于tkinter画布的高可定制性,可见我的另一个小项目,基于tkinter画布的现代元素控件库。
本文将以TinML的<n>(<note>)
标签为例,讲解新TinML实现中关于内置控件的设计。
内置控件拓展
在TinText(软件项目名称)的渲染器实现由/lib/TinEngine
负责,TinText在TinEngineCore.py
中实现,
为了保持核心文件内部的功能单纯,TinEngine另开一个controls.py
文件,用来创建需要额外拓展的内置控件。
说明与引用文本段的内置控件定义如下:
class TinTextNote(tk.Canvas):
#TinText的引用说明框
def __init__(self,tintext,width,notes,font,markcolor,fg,bg,markbg):
"""
notes:list
markcolor:str
fg:str
bg:str 画布颜色
markbg:str 文本背景色
"""
super().__init__(master=tintext,width=width,bg=bg,relief='flat',
highlightthickness=0)
self.__initialize(width,notes,font,markcolor,fg,markbg)
def __get_endy(self):
bbox=self.bbox('all')
if bbox:
return bbox[3]
else:
return 5
def __initialize(self,width,notes,font,markcolor,fg,markbg):
for i in notes:
self.create_text((7,self.__get_endy()),text=i,font=font,fill=fg,anchor='nw',width=width-14)
bbox=self.bbox('all')
back=self.create_polygon((bbox[0],5,width-2,5,width-2,bbox[3],bbox[0],bbox[3]),
fill=markbg,outline=markbg,width=7)
self.create_line((2,5,2,bbox[3]),fill=markcolor,width=3,capstyle='round',joinstyle='round')
self.lower(back)
bbox=self.bbox('all')
height=bbox[3]-bbox[1]
self.config(height=height)
功能很简单,就是根据TinText自身的样式、引用文本、TinText宽度,绘制一个说明与引用文本块样式的华埠元素集合。关于tkinter画布绘制功能控件的详细说明,可见我的TinUI专栏,当然,这里不需要绘制可交互的功能元素,但保不准之后会需要。
嵌入内置空间
在TinText的初始化中,使用了self.widgets=list()
代码,用来创建一个收集所有内置控件对象的列表,用来在必要时刻删除这些内置控件,减小不必要的内存消耗。
TinText渲染<n>
的方法如下:
def __render_note(self,notes):
#引用说明
self.update()
width=self.winfo_width()
note=TinTextNote(self,width,notes,self.cget('font'),'#5969e0','#7e7e7e',self.cget('background'),'#f9f9f9')
self.widgets.append(note)
self.window_create('end',window=note,align='center')
self.insert('end','\n')
这样的方法同样可以运用在其它任何需要用到自定义拓展空间的地方,保证核心文件就是负责解析和渲染,也方便进行维护。