tkinter绘制组件(23)——列表框

2024-04-10 14:18

本文主要是介绍tkinter绘制组件(23)——列表框,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

tkinter绘制组件(23)——列表框

  • 引言
  • 布局
    • 函数结构
    • 组件框架
    • 绑定滚动条
    • 不同于combobox的逻辑
    • 添加可选元素
    • 绑定样式
    • 完整代码函数
  • 效果
    • 测试代码
    • 最终效果
    • 2023-1-15新功能
  • pip下载
  • 修改开源协议
  • 结语

引言

与TinUI的下拉框(组合框)combobox类似,列表框也是向用户显示若干个可选择的提示文本段,待用户点击选择后调用响应的函数,并且传递选择的参数,也就是被选中的文本段文字。那么这两个组件矛盾吗?当然不矛盾。

combobox的应用场景:

  • 有限元素个数

  • 文本长度短

总结起来就是小而精。而listbox的应用场景:

  • 很多个可选内容

  • 可选文本长短、格式相差巨大,一般为长文本或复杂格式文本

  • 占用位置固定

所以说,这两个组件实际上是互补的。再加上TinUI已经完成了滚动条的绘制,为这些视野可变的组件创建打下了基础。


布局

函数结构

def add_listbox(self,pos:tuple,width:int=200,height:int=200,font='微软雅黑 12',data=('a','b','c'),bg='#f2f2f2',fg='black',activebg='#e9e9e9',sel='#b4bbea',anchor='nw',command=None):#绘制列表框'''pos::起始位置width::宽度height::高度font::字体data::一元元素集,可选提示文本数据bg::背景色fg::文本和滚动条颜色activebg::响应鼠标的背景颜色sel::选中时背景颜色anchor::对齐方向command::回调函数,必须接受一个参数,被选中的文本'''

组件框架

因为需要使用到滚动条,我们使用两个BasicTinUI组件嵌套。

        frame=BasicTinUI(self,bg=bg)#主显示框,显示滚动条box=BasicTinUI(frame,bg=bg,width=width,height=height)#显示选择内容box.place(x=12,y=12)

绑定滚动条

就像平常使用tkinter原生滚动条,只不过更加简便,(对开发者)只需要一次绑定即可。这也相当于一个TinUI滚动条绑定“编外组件”的官方示例。

        uid=self.create_window(pos,window=frame,width=width+24,height=height+24,anchor=anchor)frame.add_scrollbar((width+12,12),widget=box,height=height,bg=bg,color=fg,oncolor=fg)#纵向frame.add_scrollbar((12,height+12),widget=box,height=height,direction='x',bg=bg,color=fg,oncolor=fg)#横向

不同于combobox的逻辑

你们可以认为是我的逻辑水平的提升,在listbox中,我们将使用独立的数据结构,来判断每个选项响应事件的不同反应。

这个变量如下:

choices={}#'a':[a_text,a_back,is_sel:bool]

也就是以文本内容为键,分别对应文本对象、背景框对象、选中状态的值。

添加可选元素

类似于combobox和table的重绘技术,这里不再赘述,详情请看那两篇文章。

        maxwidth=0#最大宽度for i in data:end=box.bbox('all')end=5 if end==None else end[-1]text=box.create_text((5,end+7),text=i,fill=fg,font=font,anchor='nw')bbox=box.bbox(text)twidth=bbox[2]-bbox[0]maxwidth=twidth if twidth>maxwidth else maxwidthback=box.create_rectangle((3,bbox[1]-2,bbox[2]+2,bbox[3]+2),width=0,fill=bg)box.tkraise(text)choices[i]=[text,back,False]box.tag_bind(text,'<Enter>',lambda event,text=i : in_mouse(text))box.tag_bind(text,'<Leave>',lambda event,text=i : out_mouse(text))box.tag_bind(text,'<Button-1>',lambda event,text=i : sel_it(text))box.tag_bind(back,'<Enter>',lambda event,text=i : in_mouse(text))box.tag_bind(back,'<Leave>',lambda event,text=i : out_mouse(text))box.tag_bind(back,'<Button-1>',lambda event,text=i : sel_it(text))if maxwidth<width:#判断最大宽度maxwidth=widthrepaint_back()#重绘

重绘函数如下:

        def repaint_back():for v in choices.values():bbox=box.coords(v[1])box.coords(v[1],3,bbox[1]-2,5+maxwidth+2,bbox[3]+2)

别忘了绑定可视范围。

        bbox=box.bbox('all')box.config(scrollregion=bbox)def set_y_view(event):box.yview_scroll(int(-1*(event.delta/120)), "units")box.bind('<MouseWheel>',set_y_view)

绑定样式

因为上面已经绑定了各个画布对象对鼠标的事件响应,这里直接指明绑定的函数功能。

鼠标进出事件:

        def in_mouse(t):if choices[t][2]==True:#已被选中returnbox.itemconfig(choices[t][1],fill=activebg)def out_mouse(t):if choices[t][2]==True:#已被选中box.itemconfig(choices[t][1],fill=sel)else:box.itemconfig(choices[t][1],fill=bg)

可以看到,我们通过数据结构来判断该选项是否已经被选中,如果没有,则进行样式调整,否则不做任何处理。

使用这种方法,可以避免通过画布对象的样式判断,来决定样式更改操作的冗杂过程。

选择操作:

        def sel_it(t):box.itemconfig(choices[t][1],fill=sel)choices[t][2]=Truefor i in choices.keys():if i==t:continuechoices[i][2]=Falseout_mouse(i)if command!=None:command(t)

除了使用变量数据结构的判断之外,其它比如选定、取消选定、样式恢复等逻辑和操作与combobox一样。

完整代码函数

    def add_listbox(self,pos:tuple,width:int=200,height:int=200,font='微软雅黑 12',data=('a','b','c'),bg='#f2f2f2',fg='black',activebg='#e9e9e9',sel='#b4bbea',anchor='nw',command=None):#绘制列表框def repaint_back():for v in choices.values():bbox=box.coords(v[1])box.coords(v[1],3,bbox[1]-2,5+maxwidth+2,bbox[3]+2)def in_mouse(t):if choices[t][2]==True:#已被选中returnbox.itemconfig(choices[t][1],fill=activebg)def out_mouse(t):if choices[t][2]==True:#已被选中box.itemconfig(choices[t][1],fill=sel)else:box.itemconfig(choices[t][1],fill=bg)def sel_it(t):box.itemconfig(choices[t][1],fill=sel)choices[t][2]=Truefor i in choices.keys():if i==t:continuechoices[i][2]=Falseout_mouse(i)if command!=None:command(t)frame=BasicTinUI(self,bg=bg)#主显示框,显示滚动条box=BasicTinUI(frame,bg=bg,width=width,height=height)#显示选择内容box.place(x=12,y=12)uid=self.create_window(pos,window=frame,width=width+24,height=height+24,anchor=anchor)frame.add_scrollbar((width+12,12),widget=box,height=height,bg=bg,color=fg,oncolor=fg)#纵向frame.add_scrollbar((12,height+12),widget=box,height=height,direction='x',bg=bg,color=fg,oncolor=fg)#横向choices={}#'a':[a_text,a_back,is_sel:bool]maxwidth=0#最大宽度for i in data:end=box.bbox('all')end=5 if end==None else end[-1]text=box.create_text((5,end+7),text=i,fill=fg,font=font,anchor='nw')bbox=box.bbox(text)twidth=bbox[2]-bbox[0]maxwidth=twidth if twidth>maxwidth else maxwidthback=box.create_rectangle((3,bbox[1]-2,bbox[2]+2,bbox[3]+2),width=0,fill=bg)box.tkraise(text)choices[i]=[text,back,False]box.tag_bind(text,'<Enter>',lambda event,text=i : in_mouse(text))box.tag_bind(text,'<Leave>',lambda event,text=i : out_mouse(text))box.tag_bind(text,'<Button-1>',lambda event,text=i : sel_it(text))box.tag_bind(back,'<Enter>',lambda event,text=i : in_mouse(text))box.tag_bind(back,'<Leave>',lambda event,text=i : out_mouse(text))box.tag_bind(back,'<Button-1>',lambda event,text=i : sel_it(text))if maxwidth<width:maxwidth=widthrepaint_back()bbox=box.bbox('all')box.config(scrollregion=bbox)def set_y_view(event):box.yview_scroll(int(-1*(event.delta/120)), "units")box.bind('<MouseWheel>',set_y_view)return box,uid

效果

测试代码

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 sleepfor i in range(1,101):sleep(0.02)progressgoto(i)
def test5(result):b.itemconfig(scale_text,text='当前选值:'+str(result))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 modern way to show tkinter widget in your application')m1=b.add_title((0,680),'test TinUI scrolled',size=2,angle=24)b.add_paragraph((20,290),'''     TinUI是基于tkinter画布开发的界面UI布局方案,作为tkinter拓展和TinEngine的拓展而存在。目前,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,330),350,'这里用来输入',command=print)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/')b.add_link((400,530),'执行print函数',print)_,ok1,_=b.add_waitbar1((500,220),bg='#CCCCCC')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))b.add_combobox((600,550),text='你有多大可能去珠穆朗玛峰',content=('20%','40%','60%','80%','100%','1000%'))b.add_button((600,480),text='测试进度条(无事件版本)',command=test4)_,_,_,progressgoto,_,_=b.add_progressbar((600,510))b.add_table((180,630),data=(('a','space fans over the\nworld','c'),('you\ncan','2','3'),('I','II','have a dream, then try your best to get it!')))b.add_paragraph((300,850),text='上面是一个表格')b.add_onoff((600,100))b.add_spinbox((680,100))b.add_scalebar((680,50),command=test5)scale_text,_=b.add_label((890,50),text='当前选值:2')b.add_info((680,140),info_text='this is info widget in TinUI')mtb=b.add_paragraph((0,720),'测试菜单(右键单击)')b.add_menubar(mtb,cont=(('command',print),('menu',test1),'-',('TinUI文本移动',test)))ttb=b.add_paragraph((0,800),'TinUI能做些什么?')b.add_tooltip(ttb,'很多很多')b.add_back(pos=(0,0),uids=(ttb,),bg='cyan')_,_,ok3,_=b.add_waitbar3((600,800),width=240)b.add_button((600,750),text='停止带状等待框',command=lambda event:ok3())textbox=b.add_textbox((890,100),text='这是文本输入框,当然,无法在textbox的参数中绑定横向滚动'+'\n换行'*30)[0]textbox['wrap']='none'b.add_scrollbar((1095,100),textbox)b.add_scrollbar((890,305),textbox,direction='x')b.add_listbox((890,430),data=('item1','item2','item3','item4\n item4.1\n item4.2\n item4.3\n itme4.4\n item4.5','item5 and item5.1 and item5.2 and item5.3'),command=print)a.mainloop()

最终效果

在这里插入图片描述

2023-1-15新功能

在这里插入图片描述
添加adddelete方法


github项目

TinUI的github项目地址

pip下载

pip install tinui

修改开源协议

从2022年2月开始,TinUI(包括TinUIXml技术)使用GPLv3开源协议。若要在你的软件或程序中使用TinUI,请遵照TinUI开源协议和开源条款。

开源条款见TinUI的github项目地址。

结语

TinUI推出了最新的现代化xml布局方式——TinUIXml。赶快去使用吧!!!

愿世界和平,祖国强盛

🔆tkinter创新🔆

这篇关于tkinter绘制组件(23)——列表框的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/891294

相关文章

龙蜥操作系统Anolis OS-23.x安装配置图解教程(保姆级)

《龙蜥操作系统AnolisOS-23.x安装配置图解教程(保姆级)》:本文主要介绍了安装和配置AnolisOS23.2系统,包括分区、软件选择、设置root密码、网络配置、主机名设置和禁用SELinux的步骤,详细内容请阅读本文,希望能对你有所帮助... ‌AnolisOS‌是由阿里云推出的开源操作系统,旨

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

基于Qt Qml实现时间轴组件

《基于QtQml实现时间轴组件》时间轴组件是现代用户界面中常见的元素,用于按时间顺序展示事件,本文主要为大家详细介绍了如何使用Qml实现一个简单的时间轴组件,需要的可以参考下... 目录写在前面效果图组件概述实现细节1. 组件结构2. 属性定义3. 数据模型4. 事件项的添加和排序5. 事件项的渲染如何使用

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问