tkinter绘制组件(11)——进度条
tkinter绘制组件(11)进度条
tkinter绘制组件(11)——进度条
引言
进度条在程序界面中有特殊的作用,它往往使用在处理耗时操作时,告诉用户目前程序进行的程度到哪。当然,一般的进度条是无法明确告诉用户具体的进度的,因为谁也没有办法第一时间确定处理进度,这样才会发生“卡死在99%”的“尴尬去处”。
不过,TinUI也要绘制进度条,一个能够让编写者明确设定进度的进度条,甚至能够实现进度条回退。那么,现在开工。
构思
为了实现进度条,我们需要解决以下问题:
- 能够明确设定0~100之间的整数
- 可以在进度条上显示我们想要显示的文本
- 能够通过自编函数实现进度条的动画
其中,第一和第二个功能是滚动条本身需要具备的,第三个功能是要通过创建滚动条返回的接口方法实现的。
布局
函数结构
def add_progressbar(self,pos:tuple,width=250,fg='#3B3B3B',bg='#63ADE5',percentage=True,text=''):#绘制进度条
'''
pos::位置
width::宽度
fg::文本和边框颜色
bg::进度条颜色
percentage::bool值,如果为True,则文本自动显示当前百分比;如果为False,则显示text内容
text::当percentage为False时,显示的自定的文本
'''
创建边框与进度条
不同于之前的组件绘制,因为进度条的主体是进度条本身,而不是在上面显示的文字,因此这次我们将先创建背景边框和进度条,再通过边框的位置绘制文本。
bbox=(pos[0],pos[1],pos[0]+width,pos[1]+15)
back=self.create_rectangle((bbox),outline=fg)#边框
progressbar=self.create_rectangle((pos[0],pos[1],pos[0],pos[1]+15),outline=bg,fill=bg)#进度条
绘制文字
因为TinUI的进度条文本显示提供两种方法,一种是显示进度,另一种是显示自定义文字。所以,我们需要根据参数percentage
来确定绘制哪一种文字。但无论是哪一种,都需要返回进度条显示文本。
#是否显示默认文本
if percentage==True:
text=self.create_text((pos[0]+width//2,pos[1]),anchor='n',text='0%',fill=fg,font='微软雅黑 10')
else:
text=self.create_text((pos[0]+width//2,pos[1]),anchor='n',text=text,fill=fg,font='微软雅黑 10')
设定进度
在TinUI的进度条中,我们需要一个可以设定进度的操作函数,并且该函数只能允许一个参数,就是进度。
这个参数应该能够表示为x∈[0,100]∩N。
def goto(num:int):
if not 0<=num<=100:
return
#...
Python中,
int
即整数型,接下来的数值判断即可完成参数范围判定。
借鉴之前绘制waitbar1
、waitbar2
和combobox
等组件的经验,我们可以通过函数itemconfig来设定progressbar
的样式。
但是,这有一个棘手的问题,那就是这的进度条需要改变的样式是长度,也就是矩形覆盖范围,但是覆盖范围(bbox)并不在画布对象属性设置中。那么,我们该如何改变progressbar
的长度呢?
方法也不是没有,但是得曲线救国。
我们可以放弃改变单个画布对象的样式,因为这是不可行的。干脆,每次更新进度,我们就重新绘制进度条。具体做法如下:
- 删除现有进度条
- 通过进度设定重新绘制新的进度条
- 将新的进度条绑定为特定的tag标志
那么,如何动态更新进度条,就需要用到tag这个标志来绑定我们的进度条矩形了。为了防止出现全捆绑现象,我们会将边框的ID也加入到标志名称中。
def goto(num:int):
if not 0<=num<=100:
return
pw=width*num//100
self.delete(pro_tagname)
new_progressbar=self.create_rectangle((pos[0],pos[1],pos[0]+pw,pos[1]+15),fill=bg,outline=bg)
self.lower(new_progressbar)
#将标志名称绑定到新进度条
self.addtag_withtag(pro_tagname,new_progressbar)
#是否更新默认文字
if percentage==True:
self.itemconfig(text,text=str(num)+'%')
self.update()
#...
#生成唯一tag标识
pro_tagname='progressbar>'+str(back)
self.addtag_withtag(progressbar,pro_tagname)
#...
到此,我们完成了在TinUI中绘制进度条的工作
完整代码函数
def add_progressbar(self,pos:tuple,width=250,fg='#3B3B3B',bg='#63ADE5',percentage=True,text=''):#绘制进度条
def goto(num:int):
if not 0<=num<=100:
return
pw=width*num//100
self.delete(pro_tagname)
new_progressbar=self.create_rectangle((pos[0],pos[1],pos[0]+pw,pos[1]+15),fill=bg,outline=bg)
self.lower(new_progressbar)
self.addtag_withtag(pro_tagname,new_progressbar)
if percentage==True:
self.itemconfig(text,text=str(num)+'%')
self.update()
bbox=(pos[0],pos[1],pos[0]+width,pos[1]+15)
back=self.create_rectangle((bbox),outline=fg)
progressbar=self.create_rectangle((pos[0],pos[1],pos[0],pos[1]+15),outline=bg,fill=bg)
pro_tagname='progressbar>'+str(back)
self.addtag_withtag(progressbar,pro_tagname)
#是否显示默认文本
if percentage==True:
text=self.create_text((pos[0]+width//2,pos[1]),anchor='n',text='0%',fill=fg,font='微软雅黑 10')
else:
text=self.create_text((pos[0]+width//2,pos[1]),anchor='n',text=text,fill=fg,font='微软雅黑 10')
return back,pro_tagname,text,goto
效果
测试代码
def test(event):
a.title('TinUI Test')
b.add_paragraph((50,150),'这是TinUI按钮触达的事件函数回显,此外,窗口标题也被改变、首行标题缩进减小')
b.coords(m,100,5)
def test1(word):
print(word)
def test2(event):
ok1()
def test3(event):
ok2()
def test4(event):
from time import sleep
for i in range(1,101):
sleep(0.02)
progressgoto(i)
if __name__=='__main__':
a=Tk()
a.geometry('700x700+5+5')
b=TinUI(a,bg='white')
b.pack(fill='both',expand=True)
m=b.add_title((600,0),'TinUI is a test project for futher tin using')
m1=b.add_title((0,680),'test TinUI scrolled',size=2,angle=24)
b.add_paragraph((20,290),''' TinUI是基于tkinter画布开发的界面UI布局方案,作为tkinter拓展和TinEngine的拓展而存在。目前,TinUI尚处于开发阶段。如果想要使用完整的TinUI,敬请期待。''',
angle=-18)
b.add_paragraph((20,100),'下面的段落是测试画布的非平行字体显示效果,也是TinUI的简单介绍')
b.add_button((250,450),'测试按钮',activefg='white',activebg='red',command=test,anchor='center')
b.add_checkbutton((80,430),'允许TinUI测试',command=test1)
b.add_label((10,220),'这是由画布TinUI绘制的Label组件')
b.add_entry((250,300),350,30,'这里用来输入')
b.add_separate((20,200),600)
b.add_radiobutton((50,480),300,'sky is blue, water is blue, too. So, what is your heart',('red','blue','black'),command=test1)
b.add_link((400,500),'TinGroup知识库','http://tinhome.baklib-free.com/')
_,ok1=b.add_waitbar1((500,220),bg='lightgreen')
b.add_button((500,270),'停止等待动画',activefg='cyan',activebg='black',command=test2)
bu1=b.add_button((700,200),'停止点状滚动条',activefg='white',activebg='black',command=test3)[1]
bu2=b.add_button((700,250),'nothing button 2')[1]
bu3=b.add_button((700,300),'nothing button 3')[1]
b.add_labelframe((bu1,bu2,bu3),'box buttons')
_,_,ok2=b.add_waitbar2((600,400),fg='blue')
b.add_combobox((600,550),text='中考成绩预测',content=('730','740','750','760','770','780'))
b.add_button((600,480),text='测试进度条(无事件版本)',command=test4)
_,_,_,progressgoto=b.add_progressbar((600,510))
a.mainloop()
函数test4就是实现进度条在指定范围、以指定速度、运转到指定进度的一个动态例子。
最终效果
2021-8-22新样式
2022-1-22新样式
github项目
pip下载
pip install tinui
结语
TinUI现在能够绘制等待框和进度条等动态样式组件,但是具体使用需要配合多线程和多进程来使用。因为tkinter自身的限制,当after使用多了以后,界面也是会卡住的。
🔆tkinter创新🔆
更多推荐
所有评论(0)