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

提交响应

这个操作需要有以下步骤:

  1. 获取文本框内容

  2. 设置self.over为True,问卷已经结束

  3. 响应给定的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创新🔆

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值