tkinter绘制组件(39)——滑动控件

news2024/11/13 9:24:36

tkinter绘制组件(39)——滑动控件

  • 引言
  • 布局
    • 函数结构
    • 响应按钮框架
    • 响应按钮的表示
    • 文本
    • 响应移动
    • 完整函数代码
  • 效果
    • 测试代码
    • 最终效果
  • github项目
  • pip下载
  • 结语

引言

swipecontrol直译滑动控件,参考WinUI的SwipeControl。

虽然,这个控件在平常PC端界面中不常用,因为它响应的是触摸屏或触摸板的横向滚动事件,所以不具备通用性,但是为了照顾一下希望将功能按钮隐藏在一个文本提示元素下的编写者,还是决定加入这个控件。


布局

函数结构

    def add_swipecontrol(self,pos:tuple,text:str='',height=50,width=400,fg='#1a1a1a',bg='#f3f3f3',line='#fbfbfb',data:dict={'left':({'text':'✔️\nok','fg':'#202020','bg':'#bcbcbc','command':print},),'right':({'text':'❌\nclose'},)},font=('微软雅黑',12)):#绘制滑动控件
    '''
    pos-位置
    text-文本
    height-高度
    width-宽度
    fg-文本颜色
    bg-背景颜色
    line-边框颜色
    data-按钮内容
    font-字体
    '''

响应按钮框架

这是控件的主体部分,也就是文本元素滑动后显示的内容,包括往左滑后显示的右侧内容,以及向右滑动显示的左侧内容。两部分内容互不重叠,用标记right='rights', left='left'表示。

因为显示太多个按钮在UI设计上没有意义,因此按六分之一宽度为每个按钮宽度,也就是说按钮最好不要超过六个。

控件主体使用BasicTinUI,方便滑动时文本隐藏:

        itemw=width//6#背景元素宽度。软限制为6个,多出内容没有意义
        back=BasicTinUI(self,bg=line)#背景容器
        backitem=self.create_window(pos,width=width+2,height=height+2,anchor='nw',window=back)
        uid='swipecontrol'+str(backitem)
        self.addtag_withtag(uid,backitem)
        right,left='rights','lefts'#背景元素位置
        center='centers'
        nowmode=center#当前状态

响应按钮的表示

响应按钮的内容、颜色、返回调用的函数均在data(字典)参数中表示。

data的设计结构如下:

{
    'left':(
    {'text':'content','fg':'...','bg':'...'},
    ... ,
),
    'right':(
    {'text':'content',},
    ... ,
)
}

其中,left表示左侧按钮数组,right同理。两者均可有可无。

每个按钮表示的元素是一个字典,必须包含text键,fg, bg可选,有默认值。

解析与创建的过程代码:

        if 'left' in data:#往右滑
            endx=1
            for item in data['left']:
                _bg=item['bg'] if 'bg' in item else '#bcbcbc'
                _fg=item['fg'] if 'fg' in item else '#202020'
                bitem=back.create_rectangle((endx,1,endx+itemw,1+height),fill=_bg,width=0,tags=left)
                fitem=back.create_text((endx+itemw/2,1+height/2),text=item['text'],fill=_fg,font=font,tags=left)
                command=item['command'] if 'command' in item else None
                back.tag_bind(bitem,'<Button-1>',lambda e,func=command:_docommand(func))
                back.tag_bind(fitem,'<Button-1>',lambda e,func=command:_docommand(func))
                endx+=itemw
            leftbbox=back.bbox(left)
            leftw=leftbbox[2]-leftbbox[0]
        if 'right' in data:#往左滑
            endx=width+1
            for item in data['right']:
                _bg=item['bg'] if 'bg' in item else '#bcbcbc'
                _fg=item['fg'] if 'fg' in item else '#202020'
                bitem=back.create_rectangle((endx-itemw,1,endx,1+height),fill=_bg,width=0,tags=right)
                fitem=back.create_text((endx-itemw/2,1+height/2),text=item['text'],fill=_fg,font=font,tags=right)
                command=item['command'] if 'command' in item else None
                back.tag_bind(bitem,'<Button-1>',lambda e,func=command:_docommand(func))
                back.tag_bind(fitem,'<Button-1>',lambda e,func=command:_docommand(func))
                endx-=itemw
            rightbbox=back.bbox(right)
            rightw=rightbbox[2]-rightbbox[0]

文本

        contback=back.create_rectangle((1,1,width+1,height+1),fill=bg,width=0,tags='cont')
        cont=back.create_text((3,1+height/2),anchor='w',text=text,fill=fg,font=font,tags='cont')
        back.itemconfig(left,state='hidden')
        back.itemconfig(right,state='hidden')
        back.bind('<MouseWheel>',move)
        back.tag_bind(contback,'<Button-1>',_recenter)
        back.tag_bind(cont,'<Button-1>',_recenter)

响应的事件处理:

        def _docommand(func):
            nonlocal nowmode
            time.sleep(0.01)
            _animation('center')
            nowmode=center
            if func!=None:
                func()

响应移动

swipecontrol响应三种事件:

  1. 左右滑动 - 文本滑动

  2. 按钮点击 - 响应,并重新归中

  3. 文本元素点击 - 归中

在我的一篇笔记tkinter滚动事件详解中讲到,event.state可以判断滚动的类型,但是每次滚动事件基本都是连续触发,而swipecontrol只需要响应一次。因此可以在滚动处理事件开始解绑该事件,处理完后继续监听。

        def move(event):#滚动响应
            nonlocal nowmode
            back.unbind('<MouseWheel>')    
            if event.state!=1:
                back.bind('<MouseWheel>',move)
                return    
            #...
            back.bind('<MouseWheel>',move)

然后通过对event.delta正负值、是否存在对应一侧的按钮,以及当前状态的判断,决定是否移动,往哪边移动。

注意,移动不是单纯地向右或向左,还包括居中归位。

            if event.delta<0 and 'right' in data:#左滑,显示right
                if nowmode==right:
                    back.bind('<MouseWheel>',move)
                    return
                back.itemconfig(left,state='hidden')
                back.itemconfig(right,state='normal')
                _animation('center')
                _animation('left')
                nowmode=right
            elif event.delta>0 and 'left' in data:#右滑,显示left
                if nowmode==left:
                    back.bind('<MouseWheel>',move)
                    return
                back.itemconfig(right,state='hidden')
                back.itemconfig(left,state='normal')
                _animation('center')
                _animation('right')
                nowmode=left

移动处理:

        def _animation(side):#移动动画
            if side=='left':
                for i in range(0,rightw+5,5):
                    back.move('cont',-5,0)
                    time.sleep(0.001)
                    back.update()
            elif side=='right':
                for i in range(0,leftw+5,5):
                    back.move('cont',5,0)
                    time.sleep(0.001)
                    back.update()
            elif side=='center':
                if nowmode==right:
                    for i in range(0,rightw+5,5):
                        back.move('cont',5,0)
                        time.sleep(0.001)
                        back.update()
                elif nowmode==left:
                    for i in range(0,leftw+5,5):
                        back.move('cont',-5,0)
                        time.sleep(0.001)
                        back.update()

完整函数代码

    def add_swipecontrol(self,pos:tuple,text:str='',height=50,width=400,fg='#1a1a1a',bg='#f3f3f3',line='#fbfbfb',data:dict={'left':({'text':'✔️\nok','fg':'#202020','bg':'#bcbcbc','command':print},),'right':({'text':'❌\nclose'},)},font=('微软雅黑',12)):#绘制滑动控件
        def _animation(side):#移动动画
            if side=='left':
                for i in range(0,rightw+5,5):
                    back.move('cont',-5,0)
                    time.sleep(0.001)
                    back.update()
            elif side=='right':
                for i in range(0,leftw+5,5):
                    back.move('cont',5,0)
                    time.sleep(0.001)
                    back.update()
            elif side=='center':
                if nowmode==right:
                    for i in range(0,rightw+5,5):
                        back.move('cont',5,0)
                        time.sleep(0.001)
                        back.update()
                elif nowmode==left:
                    for i in range(0,leftw+5,5):
                        back.move('cont',-5,0)
                        time.sleep(0.001)
                        back.update()
        def move(event):#滚动响应
            nonlocal nowmode
            back.unbind('<MouseWheel>')
            if event.state!=1:
                back.bind('<MouseWheel>',move)
                return
            if event.delta<0 and 'right' in data:#左滑,显示right
                if nowmode==right:
                    back.bind('<MouseWheel>',move)
                    return
                back.itemconfig(left,state='hidden')
                back.itemconfig(right,state='normal')
                _animation('center')
                _animation('left')
                nowmode=right
            elif event.delta>0 and 'left' in data:#右滑,显示left
                if nowmode==left:
                    back.bind('<MouseWheel>',move)
                    return
                back.itemconfig(right,state='hidden')
                back.itemconfig(left,state='normal')
                _animation('center')
                _animation('right')
                nowmode=left
            back.bind('<MouseWheel>',move)
        def _docommand(func):
            nonlocal nowmode
            time.sleep(0.01)
            _animation('center')
            nowmode=center
            if func!=None:
                func()
        def _recenter(e):
            nonlocal nowmode
            _animation('center')
            nowmode=center
        itemw=width//6#背景元素宽度。软限制为6个,多出内容没有意义
        back=BasicTinUI(self,bg=line)#背景容器
        backitem=self.create_window(pos,width=width+2,height=height+2,anchor='nw',window=back)
        uid='swipecontrol'+str(backitem)
        self.addtag_withtag(uid,backitem)
        right,left='rights','lefts'#背景元素位置
        center='centers'
        nowmode=center#当前状态
        if 'left' in data:#往右滑
            endx=1
            for item in data['left']:
                _bg=item['bg'] if 'bg' in item else '#bcbcbc'
                _fg=item['fg'] if 'fg' in item else '#202020'
                bitem=back.create_rectangle((endx,1,endx+itemw,1+height),fill=_bg,width=0,tags=left)
                fitem=back.create_text((endx+itemw/2,1+height/2),text=item['text'],fill=_fg,font=font,tags=left)
                command=item['command'] if 'command' in item else None
                back.tag_bind(bitem,'<Button-1>',lambda e,func=command:_docommand(func))
                back.tag_bind(fitem,'<Button-1>',lambda e,func=command:_docommand(func))
                endx+=itemw
            leftbbox=back.bbox(left)
            leftw=leftbbox[2]-leftbbox[0]
        if 'right' in data:#往左滑
            endx=width+1
            for item in data['right']:
                _bg=item['bg'] if 'bg' in item else '#bcbcbc'
                _fg=item['fg'] if 'fg' in item else '#202020'
                bitem=back.create_rectangle((endx-itemw,1,endx,1+height),fill=_bg,width=0,tags=right)
                fitem=back.create_text((endx-itemw/2,1+height/2),text=item['text'],fill=_fg,font=font,tags=right)
                command=item['command'] if 'command' in item else None
                back.tag_bind(bitem,'<Button-1>',lambda e,func=command:_docommand(func))
                back.tag_bind(fitem,'<Button-1>',lambda e,func=command:_docommand(func))
                endx-=itemw
            rightbbox=back.bbox(right)
            rightw=rightbbox[2]-rightbbox[0]
        contback=back.create_rectangle((1,1,width+1,height+1),fill=bg,width=0,tags='cont')
        cont=back.create_text((3,1+height/2),anchor='w',text=text,fill=fg,font=font,tags='cont')
        back.itemconfig(left,state='hidden')
        back.itemconfig(right,state='hidden')
        back.bind('<MouseWheel>',move)
        back.tag_bind(contback,'<Button-1>',_recenter)
        back.tag_bind(cont,'<Button-1>',_recenter)
        return back,backitem

效果

测试代码

b.add_swipecontrol((320,1300),'swipe control')

最终效果

在这里插入图片描述


github项目

TinUI的github项目地址

pip下载

pip install tinui

结语

swipecontrol结合textbox可以实现列表显示功能,详见test/swipecontrol.py

🔆tkinter创新🔆

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/197116.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

凡人修C传——专栏从凡人到成仙系列目录

这里先感谢博主THUNDER王给我提出来的一个创作建议&#xff0c;让我有了创作的灵感来创建这一篇博客以及凡人修C传这一个系列的文章。 本文最主要的目的就是给大家一个凡人修C传的一个目录&#xff0c;让大家更加容易学到自己想学的地方。 &#x1f4dd;【个人主页】&#xff1…

js实现滑动进度条

效果图 完整代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widthdevic…

TOOM舆情分析和报告工具,大数据决策免费舆情监控辅助工具?

大数据舆情工具是一种利用大数据技术进行舆情监控、分析、评估和预测的工具&#xff0c;以提高企业舆情应对能力。舆情监控工具可以帮助企业提高舆情应对能力&#xff0c;提升企业形象&#xff0c;以更好地处理各种舆情问题&#xff0c;TOOM舆情分析和报告工具&#xff0c;大数…

使用Python+Tensorflow的CNN技术快速识别验证码

近年来&#xff0c;机器学习变得愈加火热&#xff0c;中国选手柯洁与AlphaGo的人机大战更是引起热议。目前&#xff0c;在图像识别和视觉分析研究中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;技术的使用越来越多。Tensorflow 是由 Google 团队开发的神经网络模块&am…

三级管集电极开路电路工作原理详细分析

今天给大家分享的是&#xff1a;集电极开路电路、集电极开路晶体管电路、集电极开路工作原理、集电极开路TTL、集电极开路输出接线图、集电极开路优缺点。 在数字芯片设计、微控制器应用和运算放大器中&#xff0c;集电极开始输出通常用于驱动继电器等高负载或用于连接其他电路…

从双钻模型看产品规划

作为产品经理&#xff0c;我们在进行产品规划的时候&#xff0c;往往是采用“探索→执行”的思维进行规划&#xff0c;然而这类方法虽然有效&#xff0c;但不全面&#xff0c;也不一定能够科学地指引我们去进行合理的产品规划。那么&#xff0c;有什么方式或模型能够让我们合理…

笔记_html

目录什么是 HTML?HTML元素(定义)骨架HTML元素a标签语法使用1-超链接使用2-锚点定位使用3-文件下载使用4-阻止a标签的默认事件HTML5新增元素HTML5新增元素属性什么是 HTML? HTML是由一系列元素组成的超文本标记语言。 tips: html标签不区分大小写&#xff01; HTML元素(定义)…

多核异构处理器对共享外设和资源的调配方法-飞凌嵌入式

来源&#xff1a;飞凌嵌入式官网www.forlinx.com在多核异构CPU中&#xff0c;多个内核就如同多个大脑&#xff0c;而外设和内存等资源就如同手足&#xff0c;那么多个大脑该如何控制手足才能保证它们正常有序地运行呢&#xff1f;以NXP i.MX8M Plus处理器的A核和M核为例&#x…

为HTML网页添加喜庆气氛的诸多方法

为HTML网页添加喜庆气氛的诸多方法 节假日&#xff0c;如春节&#xff0c;为网页&#xff08;或网站的主网页&#xff09;营造欢乐祥和氛围的手段&#xff0c;还是比较多的&#xff0c;下面介绍。 先给出未加喜庆气氛修饰的网页源码如下&#xff0c;特意做的简单&#xff0c;意…

Docker - 10. 本地镜像发布到阿里云

将本地镜像发布到阿里云&#xff0c;具体步骤如下&#xff1a; 1. 注册并登录阿里云控制台&#xff1a;阿里云登录平台 2. 进入容器镜像服务&#xff1a;阿里云 - 容器镜像服务 3. 创建个人实例&#xff0c;未创建前如下图1&#xff0c;创建后见下图2 4. 打开并创建命名空间…

XSS Labs (one)

Web Security Academy>>Cross-site scripting>>Contexts burpsuite官网XSS靶场地址 超全的fuzz payload Lab: Reflected XSS into HTML context with nothing encoded <script>alert(1)</script>弹出成功&#xff0c;最简单的反射型XSS靶场。 Lab: S…

2023牛客寒假算法基础集训营5 小沙の不懂(思维)

题意&#xff1a;这题目一开始看了半天啊&#xff0c;而且坑点很多&#xff08;qwq&#xff09;&#xff0c;大概意思就是给你两个字符串a,b&#xff08;可能存在前导0&#xff09;&#xff0c;然后给你任意个长度为10的从0到9的排列&#xff08;比如1234567890 &#xff0c;09…

攻防世界:crypt(RC4)

1、下载PE文件&#xff0c;控制台程序2、main函数大致分析&#xff0c;请看下面的注释int __cdecl main(int argc, const char **argv, const char **envp) {unsigned int str_length; // eaxunsigned int myflag_length; // eaxvoid *v5; // raxvoid *v7; // raxint i; // [rs…

软测(概念) · 开发模型 · 软件的生命周期 · 瀑布模型 · 螺线模型 · 增量模型 · 迭代模型 · 敏捷模型 · scrum · 软件测试模型之 V 模型 W 模型

一、开发模型的由来二、软件的生命周期三、瀑布模型&#xff08;Waterfall Model&#xff09;四、螺线模型&#xff08;Spiral Model&#xff09;五、增量模型&#xff08;Incremental Model&#xff09;六、迭代模型&#xff08;Rational UnifiedProcess&#xff09;七、敏捷模…

SQL Server 2014 数据库误删数据的恢复处理

一、序言 作为程序开发人员或 DBA&#xff0c;经常会接触到数据库&#xff08;以 SQL Server 2014 数据库为例&#xff09;的增、删、改查操作。执行 delete 语句时不小心误删数据表的记录情况&#xff0c;而数据库之前又没有任何备份。 SQL Server 数据库自身的数据库还原数…

使用蚁群优化 (ACO) 解决背包问题(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 背包问题&#xff08;Knapsack problem&#xff09;是一种组合优化的NP完全&#xff08;NP-Complete&#xff0c;NPC&#xff0…

【My Electronic Notes系列——组合逻辑电路】

目录 序言&#xff1a; &#x1f3c6;&#x1f3c6;人生在世&#xff0c;成功并非易事&#xff0c;他需要破茧而出的决心&#xff0c;他需要永不放弃的信念&#xff0c;他需要水滴石穿的坚持&#xff0c;他需要自强不息的勇气&#xff0c;他需要无畏无惧的凛然。要想成功&…

【页面设计】03.JavaScript

一、什么是JavaScript&#xff1f; 一种编程语言&#xff0c;可以在网页上实现复杂的功能、交互等。是一种解释型语言&#xff0c;也是一种面向对象的语言。 ps&#xff1a;解释型语言&#xff0c;是在运行的时候将程序翻译成机器语言。解释型语言的程序不需要在运行前编译&a…

怎么找回删除的文件?尝试下这些恢复数据的方法

我们使用电脑时&#xff0c;总会产生各种各样的文件数据。这些文件保存在电脑里面&#xff0c;但是有时不免手滑误删重要的文件。这些文件被删除、被清空了&#xff0c;还可以恢复回来吗&#xff1f;怎么找回删除的文件&#xff1f;建议你尝试下这些恢复数据的方法。 一、文件恢…

一篇了解Eureka

文章目录一.Eureka注册中心1.1.Eureka简介1.2.Eureka基本架构1.2.1 EurekaServer(注册中心)1.2.2 EurekaClient(客户端)二.Eureka项目的构建2.1 新建一个工程EurekaServer-70012.2.将user-service注册到Eureka2.3 消费者从Eureka获取服务2.4.注册微服务信息完善三、CAP理论3.1.…