引言
又是一个莫名其妙的元素组件——列表视图(listview)。
这个组件在原生tkinter中没有对应控件,这是一个拓展组件。但是,在tkinter中不存在,不代表在其它UI库或框架不存在,就比如WinUI的ListView。
listview的重要性在于将若干个重复排版而又包含不同信息的元素呈现出来,避免占用主界面过多的位置。相比于listbox,listview在提供可选的基础上,为使用者提供了更丰富的信息,并做到整齐划一;对编写者,能够做到批量生成信息元素模块。
对于listview,最大的技术难点不是布局,因为看看,这都到了TinUI在CSDN上的第35篇文章了,一般的布局不会是问题。难点是:在tkinter可滚动控件中,鼠标进入子控件,传递滚动信息的问题。这个会在稍后讲解。
布局
函数结构
def add_listview(self,pos:tuple,width=300,height=300,linew=80,bg='#f3f3f3',activebg='#eaeaea',oncolor='#3041d8',scrobg='#f8f8f8',scroc='#999999',scrooc='#89898b',num=5,command=None):#绘制列表视图,function:add_list
'''
pos-位置
width-宽度
height-高度
linew-列表元素高度
bg-背景色
activebg-响应色
oncolor-选中标识色
scrobg-滚动条背景色
scroc-滚动条颜色
scrooc-滚动条响应色
num-列表元素数量
command-响应函数,需要一个参数接受选中项位次
'''
列表框架
为了方便样式调控,我们使用BasicTinUI
作为列表视图框架。
nowon=-1
ui=BasicTinUI(self,bg=bg)
view=self.create_window(pos,window=ui,height=height,width=width,anchor='nw')
uid='listview'+str(view)
self.addtag_withtag(uid,view)
scro=self.add_scrollbar((pos[0]+width+2,pos[1]),ui,height=height,bg=scrobg,color=scroc,oncolor=scrooc)
self.addtag_withtag(uid,scro[-1])
这里之所以选择BasicTinUI,还有一个重要原因是可以使用TinUI自己的滚动条,而不是使用tkinter的,这样可以有统一性。
列表元素
这个很简单,该怎么添加就怎么添加。
for i in range(0,num):
item=ui.add_ui((3,endy),width=width-3,height=linew,bg=bg)
items.append(item)
endy+=linew+2
item[0].bind('<Enter>',lambda event,item=item:buttonin(item))
item[0].bind('<Button-1>',lambda event,item=item:click(item))
item[0].bind('<Leave>',lambda event,item=item:buttonout(item))
标识元素
这里的表示元素是模仿winui的。也就是在列表元素左侧有一个高度大概为元素高度三分之一的线条,以作为标识元素。
lineheight=linew/3
line=ui.create_line((1,linew/3,1,linew*2/3),fill=oncolor,width=3,capstyle='round')
滚动范围和背景
滚动范围就是ui内所有元素了,而背景就不用再自己绘制了,直接使用TinUI的back
。
ui.config(scrollregion=ui.bbox('all'))
ui.move(line,0,-linew-height)
self.add_back((),(view,scro[-1]),fg=bg,bg=bg,linew=3)
滚动信息传递
这个部分是重点,虽然不难,但是是一个需要注意的地方。
如果只为BasicTinUI绑定滚动,那这个控件基本费了。当鼠标进入某一个列表元素时,是滚不动的。
因此,需要将每一个列表元素的滚动信息都往上传。
def bindyview(event):
ui.yview_scroll(int(-1*(event.delta/120)), "units")
#...
for i in range(0,num):
#...
item[0].bind('<MouseWheel>',bindyview)
选择功能
这个部分参考listbox。
def buttonin(itui):
itui[0]['background']=activebg
def buttonout(itui):
if items.index(itui)!=nowon:
itui[0]['background']=bg
def click(itui):
nonlocal nowon
index=items.index(itui)
items[nowon][0]['background']=bg
nowon=index
items[nowon][0]['background']=activebg
ui.coords(line,1,index*(linew+2)+lineheight,1,index*(linew+2)+lineheight*2)
if command!=None:
command(nowon)
完整函数代码
def add_listview(self,pos:tuple,width=300,height=300,linew=80,bg='#f3f3f3',activebg='#eaeaea',oncolor='#3041d8',scrobg='#f8f8f8',scroc='#999999',scrooc='#89898b',num=5,command=None):#绘制列表视图,function:add_list
def buttonin(itui):
itui[0]['background']=activebg
def buttonout(itui):
if items.index(itui)!=nowon:
itui[0]['background']=bg
def click(itui):
nonlocal nowon
index=items.index(itui)
items[nowon][0]['background']=bg
nowon=index
items[nowon][0]['background']=activebg
ui.coords(line,1,index*(linew+2)+lineheight,1,index*(linew+2)+lineheight*2)
if command!=None:
command(nowon)
def bindyview(event):
ui.yview_scroll(int(-1*(event.delta/120)), "units")
nowon=-1
ui=BasicTinUI(self,bg=bg)
view=self.create_window(pos,window=ui,height=height,width=width,anchor='nw')
uid='listview'+str(view)
self.addtag_withtag(uid,view)
scro=self.add_scrollbar((pos[0]+width+2,pos[1]),ui,height=height,bg=scrobg,color=scroc,oncolor=scrooc)
self.addtag_withtag(uid,scro[-1])
items=[]#使用列表作为存储类型,以后可能动态修改列表视图元素
endy=0
for i in range(0,num):
item=ui.add_ui((3,endy),width=width-3,height=linew,bg=bg)
items.append(item)
endy+=linew+2
item[0].bind('<Enter>',lambda event,item=item:buttonin(item))
item[0].bind('<Button-1>',lambda event,item=item:click(item))
item[0].bind('<Leave>',lambda event,item=item:buttonout(item))
item[0].bind('<MouseWheel>',bindyview)
lineheight=linew/3
line=ui.create_line((1,linew/3,1,linew*2/3),fill=oncolor,width=3,capstyle='round')
ui.config(scrollregion=ui.bbox('all'))
ui.move(line,0,-linew-height)
self.add_back((),(view,scro[-1]),fg=bg,bg=bg,linew=3)
ui.bind('<MouseWheel>',bindyview)
return ui,scro,items,uid
效果
测试代码
lvitems=b.add_listview((1220,980))[2]
lvcontent=(
('BasicTinUI','TinUI框架渲染核心','https://tinui.smart-space.com.cn'),
('TinUI','基于tkinter的现代元素控件框架','https://smart-space.com.cn/project/TinUI/index.html'),
('CSDN','中文IT技术交流平台','https://www.csdn.net/'),
('百度','全球领先的中文搜索引擎','https://www.baidu.com/'),
('Smart-Space','一个平凡的中国人','https://smart-space.com.cn')
)
for i in range(0,5):
lvitems[i][2].loadxml(f'''<tinui>
<line>
<line>
<title text='{lvcontent[i][0]}'></title>
<link text='相关链接' url='{lvcontent[i][2]}'></link>
</line>
<line>
<label text='{lvcontent[i][1]}'></label>
</line>
</line>
</tinui>''')
最终效果
github项目
TinUI的github项目地址
pip下载
pip install tinui
结语
最近TinUI的pypi使用率上来了,但是维护频率下降了🥹。文章来源:https://www.toymoban.com/news/detail-437338.html
🔆tkinter创新🔆文章来源地址https://www.toymoban.com/news/detail-437338.html
到了这里,关于tkinter绘制组件(35)——列表视图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!