tkinter绘制组件(31)——支点标题

引言

看到这四个字——支点标题,是不是很疑惑?

其实……我写下来的时候也挺疑惑的。

这个名称(pivot)取自winui的Pivot控件,中文就是支点的意思。在winui中pivot类似于标题栏,可以让使用者决定现在要看哪一个标题对应的窗口或者内容。

当然,在TinUI中,支点标题仅仅是标题,类似于单选组控件,提高编写者对于窗口切换代码编写的高自由度。除此之外,TinUI中的支点标题可以同时横向与纵向布局,也是类似于单选组控件。虽然pivot和radiobox有很多相似之处,但是对于使用者来说则是两个完全不同的交互控件。


布局

函数结构

    def add_pivot(self,pos:tuple,fg='#959595',bg='',activefg='#525252',activecolor='#5969e0',content=(('a-title','tag1'),('b-title','tag2'),'',('c-title','tag3')),font='微软雅黑 16',padx=10,pady=10,command=None):#绘制支点标题
    '''
    pos::位置
    fg::字体颜色
    bg::创建时的保留参数
    activefg::激活时字体颜色
    activecolor::提示色
    content::内容,空字符串代表下一行
    font::字体
    padx::横向间距
    pady::纵向间距
    command::响应函数,必须接受一个参数,所选标题的tag
    '''

标题标签

标题标签指的是content参数中,每个常规元素的第二个元素,这样标题被点击时返回的不是标题名称,而是这个标签,这里叫做tag

布局框架

之前我们创建了单选组控件(radiobox),这里的布局逻辑与其相似,不清楚的可以翻回那一篇文章看看。

        texts=[]#[(text,tag,text-uid),...]
        count=-1
        select=-1#当前选定
        t_bbox=None
        nowx,nowy=pos#x坐标为左上角插入坐标,y坐标为底部坐标
        uid='pivot'+str(id(content))
        line=self.create_line((pos[0],pos[1],pos[0]+5,pos[1]),fill=activecolor,width=3,capstyle='round',tags=(uid))
        for i in content:
            count+=1#计数
            if i=='':
                if t_bbox==None:#没有底部坐标数据
                    nowy+=pady
                else:
                    nowy=t_bbox[3]+pady
                nowx=pos[0]
                texts.append(('\n','\n',None))
                continue    
            #...

这里面的line是随意位置创建的,这个元素是标题提示线。

for循环中,省略的部分就是常规标题创建,代码如下:

            text=self.create_text((nowx,nowy),font=font,text=i[0],fill=fg,anchor='nw',tags=(uid))
            t_bbox=self.bbox(text)
            width=t_bbox[2]-t_bbox[0]
            nowx=nowx+width+padx
            texts.append((i[0],i[1],text))
            self.tag_bind(text,'<Enter>',lambda event,num=count,tag=text:button_in(num,tag))
            self.tag_bind(text,'<Leave>',lambda event,num=count,tag=text:button_out(num,tag))
            self.tag_bind(text,'<Button-1>',lambda event,num=count,tag=text,tagname=i[1]:sel_it(num,tag,tagname))

绑定事件

上文中已经可以看到标题绑定了三种事件,三种事件的处理如下:

        def button_in(num,text_uid):
            if num!=select:
                self.itemconfig(text_uid,fill=activefg)
        def button_out(num,text_uid):
            if num!=select:
                self.itemconfig(text_uid,fill=fg)
        def sel_it(num,text_uid,tag):
            nonlocal select
            if num==select:
                return
            self.itemconfig(texts[select][2],fill=fg)
            select=num
            self.itemconfig(text_uid,fill=activefg)
            bbox=self.bbox(text_uid)
            self.coords(line,(bbox[0],bbox[3]+2,bbox[2],bbox[3]+2))
            if command!=None:
                command(tag)

注意的有两点:

  1. sel_it中,先恢复之前选定标题,载重新设置当前选中select

  2. 别忘了提示线移动(重绘)

默认选值

因为这个是标题内容,因此不能向单选组控件一样有空值。

在结尾加上一段代码。

        sel_it(0,texts[0][2],texts[0][1])

完整代码函数

    def add_pivot(self,pos:tuple,fg='#959595',bg='',activefg='#525252',activecolor='#5969e0',content=(('a-title','tag1'),('b-title','tag2'),'',('c-title','tag3')),font='微软雅黑 16',padx=10,pady=10,command=None):#绘制支点标题
        def button_in(num,text_uid):
            if num!=select:
                self.itemconfig(text_uid,fill=activefg)
        def button_out(num,text_uid):
            if num!=select:
                self.itemconfig(text_uid,fill=fg)
        def sel_it(num,text_uid,tag):
            nonlocal select
            if num==select:
                return
            self.itemconfig(texts[select][2],fill=fg)
            select=num
            self.itemconfig(text_uid,fill=activefg)
            bbox=self.bbox(text_uid)
            self.coords(line,(bbox[0],bbox[3]+2,bbox[2],bbox[3]+2))
            if command!=None:
                command(tag)
        texts=[]#[(text,tag,text-uid),...]
        count=-1
        select=-1#当前选定
        t_bbox=None
        nowx,nowy=pos#x坐标为左上角插入坐标,y坐标为底部坐标
        uid='pivot'+str(id(content))
        line=self.create_line((pos[0],pos[1],pos[0]+5,pos[1]),fill=activecolor,width=3,capstyle='round',tags=(uid))
        for i in content:
            count+=1#计数
            if i=='':
                if t_bbox==None:#没有底部坐标数据
                    nowy+=pady
                else:
                    nowy=t_bbox[3]+pady
                nowx=pos[0]
                texts.append(('\n','\n',None))
                continue
            text=self.create_text((nowx,nowy),font=font,text=i[0],fill=fg,anchor='nw',tags=(uid))
            t_bbox=self.bbox(text)
            width=t_bbox[2]-t_bbox[0]
            nowx=nowx+width+padx
            texts.append((i[0],i[1],text))
            self.tag_bind(text,'<Enter>',lambda event,num=count,tag=text:button_in(num,tag))
            self.tag_bind(text,'<Leave>',lambda event,num=count,tag=text:button_out(num,tag))
            self.tag_bind(text,'<Button-1>',lambda event,num=count,tag=text,tagname=i[1]:sel_it(num,tag,tagname))
        sel_it(0,texts[0][2],texts[0][1])
        return texts,uid

效果

测试代码

    #...
    b.add_pivot((1200,300),command=test10)    
    #...

最终效果

在这里插入图片描述


github项目

TinUI的github项目地址

pip下载

pip install tinui

结语

自我感觉,这个比tkinter原生的标题框好看多了。

🔆tkinter创新🔆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值