引言
wow,便笺(notecard)已经是TinUI的第三十个功能组件了。顺带说一下,隔壁CustomTkinter真的是巨好用。
首先,我们来看看便笺的“笺”怎么读,我们知道,便笺(jiān)在日常生活中实际上是一种提示工具,也就是自我提示或提示他人的一种媒介。那么桌面窗口也同样会遇到这种情况:编写者想让使用者知道些什么,或者是使用者想提醒自己什么。
那么,便笺便排上用场了。
布局
函数结构
def add_notecard(self,pos:tuple,title='note',text='note text\nmain content',tfg='black',tbg='#fbfbfb',fg='black',bg='#f4f4f4',sep='#e5e5e5',width=200,font='微软雅黑 12'):#绘制便笺
'''
pos::位置
title::标题文本
text::内容文本
tfg::标题文本颜色
tbg::标题背景色
fg::内容文本颜色
bg::内容文本背景色
sep::边框、分割线颜色
width::文本宽度
font::字体
'''
元素布局
虽然我们有一个sep
参数,但那是我最初构想的一个参数,也就是分割线颜色,因为后来的一些改动,这个参数保留,但其含义已经成为了边框背景色。这里,我们不妨看看便笺都有哪些元素:
-
大背景
-
标题
-
文本内容(与标题之间有间隔,这个间隔看起来像分割线)
没错,第三点挺重要的。
标题
不要问我为什么单独创建标题,而不是将内容连在标题后面一同创建。这个设计是为了未来的某一次更新的,方便将来的元素绘制😏。
toptext=self.create_text((pos[0]+10,pos[1]+10),text=title,font=font,fill=tfg,width=width,anchor='nw')#标题
uid='notecard'+str(toptext)
self.addtag_withtag(uid,toptext)
tx1,ty1,tx2,ty2=self.bbox(toptext)
if tx2-tx1<width:#判读当前文本宽度
tx2=tx1+width
topback=self.create_polygon((tx1,ty1,tx2,ty1,tx2,ty2,tx1,ty2),outline=tbg,fill=tbg,width=10,tags=uid)
值得注意的是,这里我们使用polygon
,能够绘制圆角背景
内容文本
这里只需要注意与标题有一定的间隔就行了。
content=self.create_text((tx1,ty2+12),text=text,font=font,fill=fg,width=width,anchor='nw',tags=uid)#便笺内容
cx1,cy1,cx2,cy2=self.bbox(content)
if cx2-cx1<width:
cx2=cx1+width
contentback=self.create_polygon((cx1,cy1,cx2,cy1,cx2,cy2,cx1,cy2),outline=bg,fill=bg,width=10,tags=uid)
大背景
这个背景真的是辛苦,既要做背景,还要附带边框、分割线的效果。管他呢~。
ax1,ay1,ax2,ay2=self.bbox(uid)#大背景
ax1+=5
ay1+=5
ax2-=5
ay2-=5
allback=self.create_polygon((ax1,ay1,ax2,ay1,ax2,ay2,ax1,ay2),outline=sep,fill=sep,width=10,tags=uid)
调整元素层级
刚才我们创建了所需要的元素,现在调整一下层级。
#调整元素层级关系
self.tkraise(topback)
self.tkraise(toptext)
self.tkraise(contentback)
self.tkraise(content)
绑定拖动事件
便笺怎么能够没办法拖拽呢?其实TinUI早就有很多拖拽控件了,这里直接给代码。不熟悉的朋友可以查看TinUI的调节框、滚动条等。
#绑定拖动事件
self.tag_bind(topback,'<Button-1>',mousedown)
self.tag_bind(topback,'<B1-Motion>',drag)
self.tag_bind(toptext,'<Button-1>',mousedown)
self.tag_bind(toptext,'<B1-Motion>',drag)
以下是相关回调函数:
def mousedown(event):
nonlocal startx,starty
startx=self.canvasx(event.x)#定义起始横坐标
starty=self.canvasy(event.y)
def drag(event):
nonlocal startx,starty
nowx=self.canvasx(event.x)
nowy=self.canvasy(event.y)
movex=nowx-startx#将窗口坐标转化为画布坐标
movey=nowy-starty
self.move(uid,movex,movey)
#重新定义画布中的起始拖动位置
startx=nowx
starty=nowy
完整代码函数
def add_notecard(self,pos:tuple,title='note',text='note text\nmain content',tfg='black',tbg='#fbfbfb',fg='black',bg='#f4f4f4',sep='#e5e5e5',width=200,font='微软雅黑 12'):#绘制便笺
def mousedown(event):
nonlocal startx,starty
startx=self.canvasx(event.x)#定义起始横坐标
starty=self.canvasy(event.y)
def drag(event):
nonlocal startx,starty
nowx=self.canvasx(event.x)
nowy=self.canvasy(event.y)
movex=nowx-startx#将窗口坐标转化为画布坐标
movey=nowy-starty
self.move(uid,movex,movey)
#重新定义画布中的起始拖动位置
startx=nowx
starty=nowy
startx,starty=None,None#拖动记录点
toptext=self.create_text((pos[0]+10,pos[1]+10),text=title,font=font,fill=tfg,width=width,anchor='nw')#标题
uid='notecard'+str(toptext)
self.addtag_withtag(uid,toptext)
tx1,ty1,tx2,ty2=self.bbox(toptext)
if tx2-tx1<width:#判读当前文本宽度
tx2=tx1+width
topback=self.create_polygon((tx1,ty1,tx2,ty1,tx2,ty2,tx1,ty2),outline=tbg,fill=tbg,width=10,tags=uid)
content=self.create_text((tx1,ty2+12),text=text,font=font,fill=fg,width=width,anchor='nw',tags=uid)#便笺内容
cx1,cy1,cx2,cy2=self.bbox(content)
if cx2-cx1<width:
cx2=cx1+width
contentback=self.create_polygon((cx1,cy1,cx2,cy1,cx2,cy2,cx1,cy2),outline=bg,fill=bg,width=10,tags=uid)
ax1,ay1,ax2,ay2=self.bbox(uid)#大背景
ax1+=5
ay1+=5
ax2-=5
ay2-=5
allback=self.create_polygon((ax1,ay1,ax2,ay1,ax2,ay2,ax1,ay2),outline=sep,fill=sep,width=10,tags=uid)
#调整元素层级关系
self.tkraise(topback)
self.tkraise(toptext)
self.tkraise(contentback)
self.tkraise(content)
#绑定拖动事件
self.tag_bind(topback,'<Button-1>',mousedown)
self.tag_bind(topback,'<B1-Motion>',drag)
self.tag_bind(toptext,'<Button-1>',mousedown)
self.tag_bind(toptext,'<B1-Motion>',drag)
return toptext,content,uid
效果
测试代码
#...
b.add_notecard((1200,50))
#...
这个测试代码真的是越来越简了。。。
最终效果
github项目
pip下载
pip install tinui
结语
TinUI接下来的主要任务是改进控件,关于新增模块欢迎通过电子邮箱投递。
🔆tkinter创新🔆