tkinter-TinUI-xml实战(6)问卷
引言
电子问卷可以方便地获取大量受访者态度信息,具有高效性和环保性。那么在普通的应用中,问卷可以用来做意见反馈、未来决策参考等重要的信息收集行为。
在tkinter,并没有现成的问卷系统拓展库。那我们不妨使用TinUI来写一个简单的问卷控件,为大家作参考使用。
该问卷控件实际上是对TinUI的操作类,不是一个完全的控件实例。本次问卷控件仅实现填写、收集等简单功能。
声明
本项目属于作者原创。借鉴了GitHub/TinUI上的tuxml.py
,翻版必究,但可以自行添加功能代码。
本项目使用的TinUI为我开源并维护在GitHub上的主文件——TinUI.py。当然,使用PYPI中下载安装的tinui也可以。
文件结构
-
tinui.py - TinUI核心支持
-
问卷.py - 本次的源码文件
核心代码
因为本次属于动态UI元素添加,而且布局简单,所以暂时不想写TinUIXaml。
操作类
ATW
是随便起的名称。
class ATW():
def __init__(self,tinui,command=None,content=[['radio','select radio',('a','b','c')],['check','select some',('1','2','3','4','5')],['input','input something','input>>'],['text','write something in textbox','text it>>'],['rating','do you like it',5]]):
'''
要操作的TinUI类
点击提交按钮后执行的函数
问卷内容
'''
问卷内容参数设计
问卷内容参数content
采用列表式标签型文本设计。
content=[(tag,text,val),...]
-
tag 标签
-
radio 单选
-
check 多选
-
input 单行输入
-
text 文本框输入
-
rating 评星
-
-
text 问题文本
-
val 相应类型的选值
获取TinUI最下方位置
也就是取得最下方左侧点的坐标。
def end(pady=2):
bbox=self.ui.bbox('all')
if bbox==None:
return (5,5)
else:
return (5,bbox[3]+pady)
初始化属性
以下是初始化代码:
def __init__(self,tinui,command=None,content=[['radio','select radio',('a','b','c')],['check','select some',('1','2','3','4','5')],['input','input something','input>>'],['text','write something in textbox','text it>>'],['rating','do you like it',5]]):
self.answer=list()#结果
self.over=False#是否结束
self.content=content#问卷内容
self.command=command#结束函数
self.ui=tinui
for i in content:#提前初始化总数据
self.answer.append('')#初始化结果个数
self.inputbar=list()#[(entry|text,num),...],用于最终获取内容
值得注意的是,输入框类无法直接获取选值,因此将它们储存到self.inputbar
中,当点击提交按钮后再获取。
元素布局
def show(self):
def end(pady=2):
bbox=self.ui.bbox('all')
if bbox==None:
return (5,5)
else:
return (5,bbox[3]+pady)
count=0
for ask in self.content:
ask[1]=str(count+1)+'. '+ask[1]
if ask[0]=='radio':
self.ui.add_paragraph(end(8),text=ask[1])
self.ui.add_radiobox(end(),content=ask[2],command=lambda text,c=count:self.get_radio(c,text))
elif ask[0]=='check':
self.answer[count]=list()
self.ui.add_paragraph(end(8),text=ask[1])
for i in ask[2]:
self.ui.add_checkbutton(end(),text=i,command=lambda event,text=i,c=count:self.get_check(c,text))
elif ask[0]=='input':
self.ui.add_paragraph(end(8),text=ask[1])
entry=self.ui.add_entry(end(),width=400,text=ask[2])[0]
self.inputbar.append((entry,count,'entry'))
elif ask[0]=='text':
self.ui.add_paragraph(end(8),text=ask[1])
text=self.ui.add_textbox(end(),width=400,text=ask[2],scrollbar=True)[0]
self.inputbar.append((text,count,'text'))
elif ask[0]=='rating':
self.ui.add_paragraph(end(8),text=ask[1])
self.ui.add_ratingbar(end(),linew=10,num=ask[2],command=lambda rate,c=count:self.get_rating(c,rate))
count+=1
self.ui.add_button(end(10),text='提交答案',command=self.over_it)
注意到checkbutton的按钮响应存在默认值
event
。
获取按钮值
def get_radio(self,num,text):
self.answer[num]=text
def get_check(self,num,text):
if text not in self.answer[num]:
self.answer[num].append(text)
else:
self.answer[num].remove(text)
def get_rating(self,num,rate):
self.answer[num]=rate
提交响应
这个操作需要有以下步骤:
-
获取文本框内容
-
设置
self.over
为True,问卷已经结束 -
响应给定的
self.command
def over_it(self,*e):
for bar in self.inputbar:
if bar[2]=='entry':
content=bar[0].get()
elif bar[2]=='text':
content=bar[0].get(1.0,'end')
self.answer[bar[1]]=content
self.over=True
if self.command!=None:
self.command()
编写者获取答案
这个方法天经地义,但是,要是使用者没有提交呢?这可能又有编写者想强行获取当前答案。那么,我们再加上一个有判断的获取函数吧。
def get(self,must=False):
if self.over:
return self.answer
else:
if must:#必须返回
return self.answer
else:
return None
完整类函数
class ATW():
def __init__(self,tinui,command=None,content=[['radio','select radio',('a','b','c')],['check','select some',('1','2','3','4','5')],['input','input something','input>>'],['text','write something in textbox','text it>>'],['rating','do you like it',5]]):
self.answer=list()
self.over=False#是否结束
self.content=content
self.command=command
self.ui=tinui
for i in content:#提前初始化总数据
self.answer.append('')
self.inputbar=list()#[(entry|text,num),...]
def get_radio(self,num,text):
self.answer[num]=text
def get_check(self,num,text):
if text not in self.answer[num]:
self.answer[num].append(text)
else:
self.answer[num].remove(text)
def get_rating(self,num,rate):
self.answer[num]=rate
def over_it(self,*e):
for bar in self.inputbar:
if bar[2]=='entry':
content=bar[0].get()
elif bar[2]=='text':
content=bar[0].get(1.0,'end')
self.answer[bar[1]]=content
self.over=True
if self.command!=None:
self.command()
def show(self):
def end(pady=2):
bbox=self.ui.bbox('all')
if bbox==None:
return (5,5)
else:
return (5,bbox[3]+pady)
count=0
for ask in self.content:
ask[1]=str(count+1)+'. '+ask[1]
if ask[0]=='radio':
self.ui.add_paragraph(end(8),text=ask[1])
self.ui.add_radiobox(end(),content=ask[2],command=lambda text,c=count:self.get_radio(c,text))
elif ask[0]=='check':
self.answer[count]=list()
self.ui.add_paragraph(end(8),text=ask[1])
for i in ask[2]:
self.ui.add_checkbutton(end(),text=i,command=lambda event,text=i,c=count:self.get_check(c,text))
elif ask[0]=='input':
self.ui.add_paragraph(end(8),text=ask[1])
entry=self.ui.add_entry(end(),width=400,text=ask[2])[0]
self.inputbar.append((entry,count,'entry'))
elif ask[0]=='text':
self.ui.add_paragraph(end(8),text=ask[1])
text=self.ui.add_textbox(end(),width=400,text=ask[2],scrollbar=True)[0]
self.inputbar.append((text,count,'text'))
elif ask[0]=='rating':
self.ui.add_paragraph(end(8),text=ask[1])
self.ui.add_ratingbar(end(),linew=10,num=ask[2],command=lambda rate,c=count:self.get_rating(c,rate))
count+=1
self.ui.add_button(end(10),text='提交答案',command=self.over_it)
def get(self,must=False):
if self.over:
return self.answer
else:
if must:#必须返回
return self.answer
else:
return None
测试
测试代码
r=Tk()
r.title('问卷系统')
r.geometry('500x400+50+50')
ui=TinUI(r)
ui.pack(fill='both',expand=True)
atw=ATW(ui,command=print_over)
atw.show()
r.mainloop()
效果
使用测试
问卷内容
简单一点的设计:
real_list=[
['radio','你喜欢用tkinter吗',('yes','no')],
['radio','你更喜欢哪个tkinter控件库',('tkinter','customtkinter','tinui')],
['check','你学习tkinter的途径',('课程','辅导书','网络','自己摸索')],
['input','你对使用tkinter的想法',''],
['rating','你对当前tkinter的拓展库开发情况满意程度',5]
]
效果
结语
至此,我们完成了一个简单的问卷操作类,感兴趣的朋友可以在此基础上开发出一个问卷系统。关于问卷数据处理,就是仁者见仁智者见智了。
TinUI现在有了33个正规元素控件了。
🔆tkinter创新🔆