赞
踩
其实,光看到TinUI这个控件的名称——“单选组控件”,是否想起了之前的TinUI单选框?
事实上,单选组控件(radiobox)与单选框的功能很像,都是允许使用者确定一个唯一的选项,以此让程序决定去做些什么。但是,这两者真的重复吗?不尽然,首先看看radiobutton的一些不足,或者说是特点:
固化规定了是问题类型的单选情形
竖直排列布局
样式为TinUI原创样式
当然,以上内容并不能说是单选框的缺点,而只能说它的专一项目。因此,radiobutton更像是一个封装好的控件,而单选组控件则像是一个标准控件。当然,它们两个不能互相替代,这也就是为TinUI加上radiobox控件的原因。
最近有人提议为radiobutton添加边框参数,以及加入add_image函数。但是希望大家把要求说明白些,否则我也无从下手,因为我还有自己的改进计划。
def add_radiobox(self,pos:tuple,fontfg='black',font='微软雅黑 12',fg='#8b8b8b',bg='#ededed',activefg='#898989',activebg='#e5e5e5',onfg='#3041d8',onbg='#ffffff',content:tuple=('1','','2'),padx=10,pady=5,command=None):#绘制单选组控件
'''
- pos::位置
- fontfg::文本颜色
- fg::标识符边框颜色
- bg::标识符背景颜色
- activefg::鼠标进入标识符边框颜色
- activebg::鼠标进入标识符背景颜色
- onfg::选定标识符边框颜色
- onbg::选定标识符背景颜色
- content::选择文本内容。如果为空字符串则代表换行
- padx::水平间距
- pady::行间距
- command::回调函数,必须接受一个参数,所选选项的文本
'''
这里所说的固定元素,包括:
标识符常态直径和边框宽度
标识符激活时直径和边框宽度
boxes
字典,用于放置每一个单选元素的标识符、文本、背景
当前选择项目(初始化为-1
)
#标识符内部宽度width和边框宽度line
back_width=16
back_line=1#16+1*2=18
#active... = back...
on_width=8
on_line=4#8+(4+1)*2=18
boxes=[]#[(sign_id,text_id,back_id),...],换行为(None,'\n',None)
nowx,nowy=pos#x坐标为左上角插入坐标,y坐标为底部坐标
uid='radiobox'+str(id(pos))
select=-1#当前选定
count=-1
t_bbox=None
这些文本都在元组content
里,但是,我们不可能只有横向布局吧,如何让TinUI知道应该在新的一行布置单选元素呢?那就是使用文本元组中的空字符。当字符串为空时,则代表新增一行。值得注意的是,当目前没有任何单选元素,也就是前面没有任何文本或全是空字符时,我们往下加行的纵坐标边行量就是pady
,当本行存在单选元素时,就再加上本行高度即可。
for i in content: count+=1#计数 if i=='': if t_bbox==None:#没有底部坐标数据 nowy+=pady else: nowy=t_bbox[3]+pady nowx=pos[0] boxes.append((None,'\n',None)) continue x1=nowx+back_line y1=nowy+back_line x2=nowx+back_line+back_width y2=nowy+back_line+back_width ar=(x1,y1,x2,y2) sign=self.create_oval(ar,width=back_line,fill=bg,outline=fg,tags=uid) text=self.create_text((x2+5,nowy),text=i,font=font,fill=fontfg,anchor='nw',tags=uid) s_bbox=self.bbox(sign) t_bbox=self.bbox(text) back=self.create_rectangle((s_bbox[0],s_bbox[1],t_bbox[2],t_bbox[3]),width=0,fill='',tags=uid) boxes.append((sign,text,back)) nowx=t_bbox[2]+padx
back
元素是背景元素,其填充色为透明,但是层级在标识符元素和文本元素之上,因此虽然我们点击的是单选元素,但实际上是覆盖在其上的一层“膜”,而标识符只负责变化提示色。随着时间的推移,我对TinUI开发的逻辑正在持续优化>^<。
def button_in(area,sel,sign):
if sel==select:
return
self.itemconfig(sign,outline=activefg,fill=activebg)
def button_out(area,sel,sign):
if sel==select:
return
self.itemconfig(sign,outline=fg,fill=bg)
这里面也有新逻辑:记录前一个选定项目,根据这个值,也就是select
的值,对前一个选定项目做出样式更改,而不是像早期一样,通过循环找到选定向。这种逻辑大大提高了运行效率。
虽然早期的逻辑代码仍然存在,有issue再改。
def sel_it(area,sel,sign):
nonlocal select
#...
项目的选定分为三个逻辑。
判断是否已经为选定项:
def sel_it(area,sel,sign):
nonlocal select
if sel==select:
return
如果有先前的选定项,则将其更换为普通样式:
#...
old_select=select#原先选定项目序号
select=sel
if old_select>=0:#恢复原先的单选组
old_sign=boxes[old_select][0]
self.itemconfig(old_sign,width=1)
button_out(None,None,old_sign)
self.update()
#...
将当前更改为选定标识样式:
self.itemconfig(sign,outline=onfg,fill=onbg,width=on_line)
if command!=None:
textid=boxes[sel][1]
text=self.itemcget(textid,'text')
command(text)
绑定样式:
self.tag_bind(back,'<Enter>',lambda event,ar=ar,sel=count,sign=sign:button_in(ar,sel,sign))
self.tag_bind(back,'<Leave>',lambda event,ar=ar,sel=count,sign=sign:button_out(ar,sel,sign))
self.tag_bind(back,'<Button-1>',lambda event,ar=ar,sel=count,sign=sign:sel_it(ar,sel,sign))
def add_radiobox(self,pos:tuple,fontfg='black',font='微软雅黑 12',fg='#8b8b8b',bg='#ededed',activefg='#898989',activebg='#e5e5e5',onfg='#3041d8',onbg='#ffffff',content:tuple=('1','','2'),padx=10,pady=5,command=None):#绘制单选组控件 def button_in(area,sel,sign): if sel==select: return self.itemconfig(sign,outline=activefg,fill=activebg) def button_out(area,sel,sign): if sel==select: return self.itemconfig(sign,outline=fg,fill=bg) def sel_it(area,sel,sign): nonlocal select if sel==select: return old_select=select#原先选定项目序号 select=sel if old_select>=0:#恢复原先的单选组 old_sign=boxes[old_select][0] self.itemconfig(old_sign,width=1) button_out(None,None,old_sign) self.update() self.itemconfig(sign,outline=onfg,fill=onbg,width=on_line) if command!=None: textid=boxes[sel][1] text=self.itemcget(textid,'text') command(text) #标识符内部宽度width和边框宽度line back_width=16 back_line=1#16+1*2=18 #active... = back... on_width=8 on_line=4#8+(4+1)*2=18 boxes=[]#[(sign_id,text_id,back_id),...],换行为(None,'\n',None) nowx,nowy=pos#x坐标为左上角插入坐标,y坐标为底部坐标 uid='radiobox'+str(id(pos)) select=-1#当前选定 count=-1 t_bbox=None for i in content: count+=1#计数 if i=='': if t_bbox==None:#没有底部坐标数据 nowy+=pady else: nowy=t_bbox[3]+pady nowx=pos[0] boxes.append((None,'\n',None)) continue x1=nowx+back_line y1=nowy+back_line x2=nowx+back_line+back_width y2=nowy+back_line+back_width ar=(x1,y1,x2,y2) sign=self.create_oval(ar,width=back_line,fill=bg,outline=fg,tags=uid) text=self.create_text((x2+5,nowy),text=i,font=font,fill=fontfg,anchor='nw',tags=uid) s_bbox=self.bbox(sign) t_bbox=self.bbox(text) back=self.create_rectangle((s_bbox[0],s_bbox[1],t_bbox[2],t_bbox[3]),width=0,fill='',tags=uid) boxes.append((sign,text,back)) self.tag_bind(back,'<Enter>',lambda event,ar=ar,sel=count,sign=sign:button_in(ar,sel,sign)) self.tag_bind(back,'<Leave>',lambda event,ar=ar,sel=count,sign=sign:button_out(ar,sel,sign)) self.tag_bind(back,'<Button-1>',lambda event,ar=ar,sel=count,sign=sign:sel_it(ar,sel,sign)) nowx=t_bbox[2]+padx return boxes,uid
def test8(rbtext):
print(f'单选组控件选值=>{rbtext}')
if __name__=='__main__':
#...
b.add_radiobox((320,1150),content=('1','2','3','','新一行内容','','单选','组','控件'),command=test8)
#...
让它圆那么一点点。。。
再圆那么一点点……
巨圆⚪……
pip install tinui
TinUI接下来的主要任务是改进控件,关于新增模块欢迎通过电子邮箱投递。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。