tkinter绘制组件(10)——组合框/下拉框
tkinter绘制组件(10)——组合框/下拉框
- 引言
- 构思
- 样式与功能(初次构想)
- 样式与功能(二次构想)
- 布局
- 函数结构
- 闭合状态下拉框
- 选项框
- 整合选项框
- 展开与闭合
- 完整代码函数
- 效果
- 测试代码
- 最终效果
- 2021-7-29新样式
- github项目
- pip下载
- 结语
引言
组合框?你一个绘制类型的TinUI框架,也想通过整合其它的个体组件来创造一个复合组件?
好吧,TinUI是不会尝试绘制可以gird或pack布局的组件的(因为tkinter画布的限制)。本篇文章想要讲的组件,是combobox。
combobox是“组合框”英译名称,而在Windows操作系统中,“combobox”有下拉框、下拉列表的含义,通常作为想给出既定选项,又不希望像单选框一样占用的一定的位置而与用户交互的组件。这次,TinUI将实现该组件。
(剧透) TinUI实现combobox
挺费劲的,是TinUI目前最复杂的个体组件。
构思
因为下拉框使用画布绘制比较复杂,先来想一下该如何实现下拉框。
样式与功能(初次构想)
基本与系统下拉框对齐(除不能够直接输入外),要基本实现以下部分:
- 初始化时有一个文本显示框和下拉提示框
- 文本显示框中应该有初始文字
- 下拉提示框响应鼠标单击动作,其文本型提示应该与下拉框的“闭合”、“展开”状态相符合
- 下拉提示框响应鼠标进入与离开动作
- 展开下拉框后,应出现只能够单选若干选项
- 各选项响应鼠标进入与离开动作
- 各选项响应鼠标单击动作,文本显示框显示选中文本,并将选中文本作为参数回调指定函数
- ……
额- - -,好像要求有点高,但是远不止这些。还有:各选项维持选定状态、下拉框响应焦点状态、文本显示框的动态更新……
先不管了,一个组件的绘制要求不能这么严格,应该从基础开始,我们就先实现这些功能……
但,还是好复杂啊…(⊙_⊙;)…(引出下文)
样式与功能(二次构想)
我认为,因为TinUI已经有了一定的规模,我们应该尝试运用以往的经验和技巧来简化下拉框的绘制。这样,才能够让之前的只是运用到我们现在要解决的问题。
combobox的整体结构我们是改不了的,但是下拉提示框可以使用add_button
替代,并且实例化其中的按钮文本和按钮背景。
下拉框的响应动作还是得自己写。
展开状态的选项列表可用借鉴add_radiobutton
的相关代码。
以下,就是绘制下拉框的新(简)版方法:
- 文本显示框和按钮
- 单选框
完事。现在开始绘制下拉框。
布局
函数结构
def add_combobox(self,pos:tuple,width:int=200,text='',content:tuple=(),fg='black',bg='white',activefg='#757F87',activebg='#CCE4F7',font=('微软雅黑',12),command=None):#绘制组合框'''pos::位置width::文本显示框宽度text::初始文本content::各个选项组成的元组fg::文本、边框颜色bg::背景色activefg::响应鼠标的文本、边框颜色activebg::响应鼠标的背景色font::字体command::回调函数。必须有一个参数:被选中的选项文本'''
闭合状态下拉框
下拉框在常规状态下,由文本显示框和下拉提示框组成。其中,下拉提示框我们会使用TinUI的按钮替代。
main=self.create_text(pos,text=text,font=font,fill=fg,anchor='nw')
bbox=self.bbox(main)
x1,y1,x2,y2=bbox[0]-3,bbox[1]-3,bbox[0]+width+3,bbox[3]+3
back=self.create_rectangle((x1,y1,x2,y2),fill=bg,outline=fg)
self.tkraise(main)
#下拉提示框
button_text,button_back=self.add_button((x2+3,y1+3),'∨',fg,bg,activefg,activebg,font=font,command=open_box)
其中,函数open_box对应了展开和闭合选项框的操作,后面再讲。
选项框
下面的代码借鉴了TinUI单选框的绘制代码。
def button_in(_tag):self.itemconfig(_tag,fill=activebg,outline=activefg)
def button_out(_tag):self.itemconfig(_tag,fill=bg,outline=fg)
start_x=bbox[0]#起始x位置height=bbox[3]+3#变量y位置for i in content:choice=self.create_text((start_x+2,height+2),text=i,fill=fg,font=(font[0],10),anchor='nw',width=width-4)pos=self.bbox(choice)h=pos[3]-pos[1]+4cho_back=self.create_rectangle((start_x,height,start_x+width,height+h),outline=fg,fill=bg)self.tkraise(choice)height+=h+2self.tag_bind(choice,'<Enter>',lambda event,back=cho_back:button_in(back))self.tag_bind(choice,'<Leave>',lambda event,back=cho_back:button_out(back))self.tag_bind(cho_back,'<Enter>',lambda event,back=cho_back:button_in(back))self.tag_bind(cho_back,'<Leave>',lambda event,back=cho_back:button_out(back))self.tag_bind(choice,'<Button>',lambda event,_text=i,back=cho_back:choose_this(back,_text))self.tag_bind(cho_back,'<Button>',lambda event,_text=i,back=cho_back:choose_this(back,_text))
这段代码取自于TinUI的radiobutton绘制代码,有删改。
这段代码的含义在TinUI绘制单选框中提到,这里不再阐述。
函数choose_this代表响应鼠标的选中动作。届时,文本显示框将显示选中的文本。
def choose_this(back,word):self.itemconfig(main,text=word)if command!=None:command(word)
整合选项框
在之后的操作中,我们需要对所有选项框进行统一操作,因此我们将为它们建立一个一致的tag名称。为了避免tag名称重复,我们将使用文本显示框和下拉提示框的组件id进行tag命名。
start_x=bbox[0]#起始x位置
height=bbox[3]+3#变量y位置
box_tagname='combobox>'+str(main)+'>'+str(back)#绑定独立的tag名称
for i in content:#...self.addtag_withtag(box_tagname,choice)self.addtag_withtag(box_tagname,cho_back)
展开与闭合
这个动作均有open_box函数进行操作。我们可以通过按钮的文本,来判断当前下拉框的状态。
首先,那些选项框本身是闭合的。
#...
for i in content:#...
self.itemconfig(box_tagname,state='hidden')
那么,函数的操作如下:
def open_box(event):if self.itemcget(button_text,'text')=='∨':self.itemconfig(button_text,text='∧',fill=activefg)self.itemconfig(box_tagname,state='normal')else:self.itemconfig(button_text,text='∨',fill=activefg)self.itemconfig(box_tagname,state='hidden')
OK,可以去吃饭了。
完整代码函数
def add_combobox(self,pos:tuple,width:int=200,text='',content:tuple=(),fg='black',bg='white',activefg='#757F87',activebg='#CCE4F7',font=('微软雅黑',12),command=None):#绘制组合框def button_in(_tag):self.itemconfig(_tag,fill=activebg,outline=activefg)def button_out(_tag):self.itemconfig(_tag,fill=bg,outline=fg)def open_box(event):if self.itemcget(button_text,'text')=='∨':self.itemconfig(button_text,text='∧',fill=activefg)self.itemconfig(box_tagname,state='normal')else:self.itemconfig(button_text,text='∨',fill=activefg)self.itemconfig(box_tagname,state='hidden')def choose_this(back,word):self.itemconfig(main,text=word)if command!=None:command(word)main=self.create_text(pos,text=text,font=font,fill=fg,anchor='nw')bbox=self.bbox(main)x1,y1,x2,y2=bbox[0]-3,bbox[1]-3,bbox[0]+width+3,bbox[3]+3back=self.create_rectangle((x1,y1,x2,y2),fill=bg,outline=fg)self.tkraise(main)button_text,button_back=self.add_button((x2+3,y1+3),'∨',fg,bg,activefg,activebg,font=font,command=open_box)start_x=bbox[0]#起始x位置height=bbox[3]+3#变量y位置box_tagname='combobox>'+str(main)+'>'+str(back)#绑定独立的tag名称for i in content:choice=self.create_text((start_x+2,height+2),text=i,fill=fg,font=(font[0],10),anchor='nw',width=width-4)pos=self.bbox(choice)h=pos[3]-pos[1]+4cho_back=self.create_rectangle((start_x,height,start_x+width,height+h),outline=fg,fill=bg)self.tkraise(choice)height+=h+2self.tag_bind(choice,'<Enter>',lambda event,back=cho_back:button_in(back))self.tag_bind(choice,'<Leave>',lambda event,back=cho_back:button_out(back))self.tag_bind(cho_back,'<Enter>',lambda event,back=cho_back:button_in(back))self.tag_bind(cho_back,'<Leave>',lambda event,back=cho_back:button_out(back))self.tag_bind(choice,'<Button>',lambda event,_text=i,back=cho_back:choose_this(back,_text))self.tag_bind(cho_back,'<Button>',lambda event,_text=i,back=cho_back:choose_this(back,_text))self.addtag_withtag(box_tagname,choice)self.addtag_withtag(box_tagname,cho_back)self.itemconfig(box_tagname,state='hidden')return main,back,box_tagname
效果
测试代码
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()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 test project for futher tin using')m1=b.add_title((0,680),'test TinUI scrolled',size=2,angle=24)b.add_paragraph((20,290),''' TinUI是基于tkinter画布开发的界面UI布局方案,作为tkinter拓展和TinEngine的拓展而存在。目前,TinUI尚处于开发阶段。如果想要使用完整的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,300),350,30,'这里用来输入')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/')_,ok1=b.add_waitbar1((500,220),bg='lightgreen')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),fg='blue')b.add_combobox((600,550),text='你有多大可能去珠穆朗玛峰',content=('20%','40%','60%','80%','100%','1000%'))a.mainloop()
最终效果
2021-7-29新样式
github项目
TinUI的github项目地址
pip下载
pip install tinui
结语
确实,TinUI的下拉框相比于系统下拉框还有细节上的不足,但是TinUI的下拉框提供了较多的自定义选项,而且不会影响使用效果。
中考考完,居然就直接写了这一篇8000+字的说明文……
欢迎到github上完善TinUI。
tkinter绘制组件(10)——组合框/下拉框相关推荐
- 自绘制HT For Web ComboBox下拉框组件
传统的HTML5的下拉框select只能实现简单的文字下拉列表,而HT for Web通用组件中ComboBox不仅能够实现传统HTML5下拉框效果,而且可以在文本框和下拉列表中添加自定义的小图标,让 ...
- 下拉框的value值怎么设置为变量_自绘制HT For Web ComboBox下拉框组件
传统的HTML5的下拉框select只能实现简单的文字下拉列表,而HT for Web通用组件中ComboBox不仅能够实现传统HTML5下拉框效果,而且可以在文本框和下拉列表中添加自定义的小图标,让 ...
- tkinter绘制组件(9)——点状等待框
tkinter绘制组件(9)--点状等待框 引言 布局 函数结构 背景 移动点 动画样式 组件与单点控制 单点移动 结束函数 完整代码函数 效果 测试代码 最终效果 2021-7-30新样式 gith ...
- html5日期不联动下拉框,下拉框联动问题 赋值时候失效
我想将三个下拉框变成一个组件 初始是没问题的 下拉福州市可以读取接口获取福州市的几个区 然后选区 查到街道 但是直接传值的时候一次性把三个都传进去导致第一个读取了 后面两个被重置了 一个一个传又破坏了 ...
- js 实现多选框(复选框) 和单选框,下拉框功能完整示例代码附效果图
<!DOCTYPE html> <html><head><meta charset="utf-8" /><script src ...
- jquery获取单选框复选框下拉框值
jquery获取单选框(radio)复选框(checkbox)下拉框(select)的值,亲测可用.有什么疑问可以留言 效果图: html代码: <!DOCTYPE html> <h ...
- php select下拉框,下拉框处理(select)
在UI自动化测试过程中,经常会遇到一些下拉框,我们有三种可选方式来操作下拉框. 第一种方法 基于webdriver的两次click,很容易出现问题,不建议使用.(由于部分下拉框在点击一次后,失去焦点再 ...
- python 下拉列表单选框怎么获取元素_JS获取文本框,下拉框,单选框的值的简单实例...
1.文本框 1.1 通过var t=document.getElementById("test").value把值赋给变量t, 1.2 当然也可以反过来把已知的变量值赋给文本框,例 ...
- vue可视化拖拽组件模板,vue自定义下拉框组件
怎样利用Vue动态生成form表单 . $formCreate参数rules 表单生成规则[inputRule,selectRule,...]options 初始化配置参数(详细见底部createOp ...
最新文章
- 信息检索报告_读者信息素养状况问卷调查分析报告来啦
- 按部就班——图解配置IIS5的SSL安全访问
- php 重定向到https,php - 如何从HTTPS重定向到HTTP? - SO中文参考 - www.soinside.com
- oracle串连接,Oracle中串连接符||的使用心得(个人见解)
- java拆分任意五位数_五位数拆分出各位 - osc_foo7glsg的个人空间 - OSCHINA - 中文开源技术交流社区...
- 华为上半年收入4540亿元;GitHub服务中断,已恢复​;Python 3.8.4发布|极客头条
- 如何通过索引从列表中删除元素?
- linux执行sh文件 查进程,linux – 用于检查进程是否已在运行的Shell脚本,如果是,则退出...
- css布局的漂浮、position定位
- 华铭智能属于芯片概念吗_华铭智能:子公司1个亿参股边缘计算独角兽九次方大数据!...
- 英特尔开源技术中心招收ROS2高手两名
- 新汽车行业的中台实践
- 英语中学生测试软件,初中生免费学英语的软件哪个好
- java进阶知识思维导图
- 七层网络性能基准测试中的协调遗漏问题--Coordinated Omission
- 抓包工具charles实践分享
- 【自然语言处理】【检索】GENER:自回归实体检索
- Java面试问题总结归纳
- GMS(Google Mobile Service)
- 笔记本计算机名称PC2019,2019值得推荐的13寸笔记本电脑汇总