• tkinter绘制组件(33)——可折叠UI


    引言

    顾名思义,这是一个可折叠的UI控件。

    UI控件自然就是TinUI了,或者是不可滚动的BasicTinUI。

    可折叠,就是说这个控件可以以一个标题框布局在某一个位置,使用者可以展开,查看其中的界面信息。

    这种控件tkinter原生想都不敢想,虽然可以做到。


    布局

    函数结构

        def add_expander(self,pos:tuple,title='expand content',tfg='black',tbg='#fbfbfb',bg='#f4f4f4',sep='#e5e5e5',width=200,height=200,scrollbar=False,font='微软雅黑 12'):#绘制一个可拓展UI
        '''
        pos-位置
        title-标题
        tfg-标题颜色
        tbg-标题框颜色
        bg-UI颜色
        sep-边框、分割线颜色
        width-UI宽度,标题宽度为 width-300
        height-UI高度
        scrollbar-是否启用TinUI
        font-字体
        '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    标题元素

    这里的标题栏和TinUI的notify类似,借鉴一下:

            toptext=self.create_text((pos[0]+10,pos[1]+10),text=title,font=font,fill=tfg,width=width-30,anchor='nw')#标题
            uid='expander'+str(toptext)
            contentid='expander-content'+str(toptext)
            self.addtag_withtag(uid,toptext)
            self.addtag_withtag(contentid,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,contentid))#标题背景
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    需要注意的是,我们需要为折叠按钮提供一定的位置,因此文本宽度是width-30

    当然这样的对于不同字号确实不妥,但是……坐等issue……

    折叠按钮

            button=self.add_button2((tx2-2,ty1-0.5),anchor='ne',text='🔻',font=font,fg=tfg,bg=tbg,activebg=bg,command=do_expand)
            self.addtag_withtag(uid,button[-1])
            self.addtag_withtag(contentid,button[-1])
    
    • 1
    • 2
    • 3

    折叠UI

    这里简单区分一下TinUI和BasicTinUI。

            if not scrollbar:#不使用滚动条,BasicTinUI
                ui=BasicTinUI(self,bg=bg)
            elif scrollbar:#使用TinUI
                ui=TinUI(self,bg=bg)
            ux=TinUIXml(ui)
            content=self.create_window((tx1,ty2+10),window=ui,anchor='nw',width=width,height=height,tags=(uid,contentid),state='hidden')#便笺内容
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后大背景。

    注意,默认折叠UI处于折叠状态,而大背景需要根据折叠状态改变大小。

            ax1,ay1,ax2,ay2=self.bbox(uid)#大背景
            ax1+=5
            ay1+=5
            ax2-=5
            allback=self.create_polygon((ax1,ay1,ax2,ay1,ax2,ay2,ax1,ay2),outline=sep,fill=sep,width=10,tags=uid)
            expand=False#当前还没有扩展
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    折叠逻辑

    这里来自于buttoncommand绑定。

            def do_expand(*e):
                nonlocal expand
                if expand==False:
                    expand=True
                    self.itemconfig(content,state='normal')
                    self.itemconfig(button[0],text='🔺')
                elif expand==True:
                    expand=False
                    self.itemconfig(content,state='hidden')
                    self.itemconfig(button[0],text='🔻')
                __size_back()
            def __size_back():#调整背景
                bx1,by1,bx2,by2=self.bbox(contentid)#大背景
                bx1+=5
                by1+=5
                bx2-=5
                self.coords(allback,bx1,by1,bx2,by1,bx2,by2,bx1,by2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    完整代码函数

        def add_expander(self,pos:tuple,title='expand content',tfg='black',tbg='#fbfbfb',bg='#f4f4f4',sep='#e5e5e5',width=200,height=200,scrollbar=False,font='微软雅黑 12'):#绘制一个可拓展UI
            def do_expand(*e):
                nonlocal expand
                if expand==False:
                    expand=True
                    self.itemconfig(content,state='normal')
                    self.itemconfig(button[0],text='🔺')
                elif expand==True:
                    expand=False
                    self.itemconfig(content,state='hidden')
                    self.itemconfig(button[0],text='🔻')
                __size_back()
            def __size_back():#调整背景
                bx1,by1,bx2,by2=self.bbox(contentid)#大背景
                bx1+=5
                by1+=5
                bx2-=5
                self.coords(allback,bx1,by1,bx2,by1,bx2,by2,bx1,by2)
            toptext=self.create_text((pos[0]+10,pos[1]+10),text=title,font=font,fill=tfg,width=width-30,anchor='nw')#标题
            uid='expander'+str(toptext)
            contentid='expander-content'+str(toptext)
            #movename='expander-move'+str(toptext)
            self.addtag_withtag(uid,toptext)
            self.addtag_withtag(contentid,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,contentid))#标题背景
            button=self.add_button2((tx2-2,ty1-0.5),anchor='ne',text='🔻',font=font,fg=tfg,bg=tbg,activebg=bg,command=do_expand)
            self.addtag_withtag(uid,button[-1])
            self.addtag_withtag(contentid,button[-1])
            if not scrollbar:#不使用滚动条,BasicTinUI
                ui=BasicTinUI(self,bg=bg)
            elif scrollbar:#使用TinUI
                ui=TinUI(self,bg=bg)
            ux=TinUIXml(ui)
            content=self.create_window((tx1,ty2+10),window=ui,anchor='nw',width=width,height=height,tags=(uid,contentid),state='hidden')#便笺内容
            ax1,ay1,ax2,ay2=self.bbox(uid)#大背景
            ax1+=5
            ay1+=5
            ax2-=5
            allback=self.create_polygon((ax1,ay1,ax2,ay1,ax2,ay2,ax1,ay2),outline=sep,fill=sep,width=10,tags=uid)
            expand=False#当前还没有扩展
            #调整元素层级关系
            self.tkraise(topback)
            self.tkraise(toptext)
            self.tkraise(button[-1])
            return toptext,ui,ux,uid
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    效果

    测试代码

    #...
        exux=b.add_expander((1200,500))[2]
        exux.loadxml('''
        
        
        
        
        
        
        ''')    
    #...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    最终效果

    在这里插入图片描述


    github项目

    TinUI的github项目地址

    pip下载

    pip install tinui
    
    • 1

    结语

    更多想法欢迎到TinUI开源库提交议题。

    TinUI有时候的更新可能是“破坏性”的,更新内容见TinUI-ChangeLog

    🔆tkinter创新🔆

  • 相关阅读:
    Java框架 Spring5--IOC
    测试 C、Python、Java 等 16 种编程语言的 Hello World:7 种存在 Bug?
    5.springcloudalibaba nacos 2.2.3源码下载并且注册服务到nacos
    完整大数据集群配置(从配置虚拟机到实操)
    Java教程:如何使用Jib插件容器化SpringBoot应用?
    python 将一个文件中的空格替换成逗号 写入新文件
    【RS】遥感影像/图片64位、16位(64bit、16bit)的意义和区别
    【MySql进阶】索引详解(三):索引的使用和创建原则、索引失效、索引优化
    Django 06
    链表相加(二)
  • 原文地址:https://blog.csdn.net/tinga_kilin/article/details/126137653