最近在工作中面向社群玩家组织了一场活动,需要进行随机抽奖,参考之前小明大佬的案例,再结合自己的需求,做了一个简单的随机抽奖小工具。
今天我就来顺便介绍一下这个小工具的制作过程吧!
1. 核心功能设计
针对随机抽奖的小工具,需要可以导入参与抽奖的人员名单,然后选择不同的奖励类型进行随机抽取获奖名单并导出。
那么,简单进行需求拆解,大致梳理出以下核心功能:
•名单导入
为了避免出现重名情况,这里我们约定以下几点:
①导入参与抽奖的人员名单文件(xlsx类型文件)
②数据第一列为ID,第二列为name
参考格式案例
•奖项类型选择
奖项类型是指一等奖、二等奖这类标识语,这里我们内置了特等奖-六等奖共7个选项供选取
•本轮人数
本轮人数是指每次抽奖时一次性抽取的获奖人数,默认值为5
①当填入的数字超过剩余未获奖人数时,会进行提示并显示未获奖人数
②当填入的数字为0表示轮空,也需要手动结束
③当填入的数字为负数时,点击抽奖无响应
④当填入的非数字时,会进行提示需要输入正确数字
•抽奖时轮播区域
用于显示抽奖中随机滚动参与本轮抽奖的人员名单
•人员名单
当选择正确的人员名单文件后,这里会自动显示人员信息列表
•中奖记录
记录每次抽取的奖项类型及获奖名单
•开始抽奖
①开始抽奖时,会先判断抽奖设置是否满足条件,否则会有相关提示
②抽奖中点击开始抽奖会提示正在抽奖中
•结束
①非抽奖状态下点击结束无响应
②抽奖中点击结束将显示本次抽奖结果
•重置
①重置会清掉历史抽奖记录(含本地文件,如有必要建议对中奖名单留档)
②抽奖中点击重置会提示正在抽奖中
③非抽奖状态点击重置会提示该操作会删除历史记录,是否确认
基本功能点确认后,我们就开始进行GUI设计。
2. GUI设计与实现
基于功能点,我们用axure简单进行UI布局设计,然后再通过GUI开发库进行设计,这里依旧采用的是pysimplegui,主要是简单方
便。
Python学习交流Q群:906715085### UI布局设计-axure 基于GUI设计,我们编码如下: nameList_column = [ [sg.Text(\'人员名单:\')], [sg.Listbox(values=[], size=(20, 10), key=\'nameList\')], ] result_column = [ [sg.Text(\'中奖记录:\')], [sg.Multiline(\'\', size=(48, 10), key=\'result\', text_color=\'DeepPink\')], ] # 主题设置 sg.theme(\'SystemDefaultForReal\') # 布局设置 layout = [[sg.Text(\'选择参与抽奖人员名单文件:\', font=(\'微软雅黑\', 12)), sg.InputText(\'\', key=\'_file\', size=(50, 1), font=(\'微软雅黑\', 10), enable_events=True), sg.FileBrowse(\'打开\', file_types=((\'Text Files\', \'*.xlsx\'),), size=(10, 1), font=(\'微软雅黑\', 11))], [sg.Frame(layout=[ [sg.Text(\'本轮奖项:\', font=(\'微软雅黑\', 12)), sg.Combo([\'特等奖\', \'一等奖\', \'二等奖\', \'三等奖\', \'四等奖\', \'五等奖\', \'六等奖\'], font=(\'微软雅黑\', 10), default_value=\'特等奖\', size=(15, 5), key=\'_type\'), sg.Text(\'本轮人数:\', font=(\'微软雅黑\', 12)), sg.InputText(\'5\', key=\'_num\', size=(38, 1), font=(\'微软雅黑\', 10))], ], title=\'抽奖设置\', title_color=\'red\', relief=sg.RELIEF_SUNKEN, tooltip=\'请进行抽奖设置后再开始抽奖\')], [sg.Multiline(size=(48, 5), font=( \'微软雅黑\', 18), text_color=\'Blue\', key=\'luckyName\', justification=\'center\')], [sg.Column(nameList_column), sg.Column(result_column)], [sg.Text(\'操作说明:\', font=(\'微软雅黑\', 12))], [sg.Text(\'①先选择参与抽奖的人员名单xlsx文件,人员名单文件包含ID和name两个字段\\n②获奖名单将存在小工具所在文件夹,重置会删除历史记录文件\', font=(\'微软雅黑\', 10)), sg.Text(\'\', font=(\'微软雅黑\', 12), size=(5, 1)), sg.Button(\'开始抽奖\', font=(\'微软雅黑\', 12), button_color=\'Orange\'), sg.Button(\'结束\', font=(\'微软雅黑\', 12), button_color=\'red\'), sg.Button(\'重置\', font=(\'微软雅黑\', 12), button_color=\'red\'), ], ] # 创建窗口 window = sg.Window(\'抽奖小工具,作者@微信公众号:可以叫我才哥\', layout, font=(\'微软雅黑\', 12), default_element_size=(50, 1))
其包含的控件如下:
•Text 文本
•InputText 输入文本框
•FileBrowse 文件浏览
•Multiline 多行文本框
•Combo 下拉框
•Listbox 列表
•Button 按钮
需要注意的是这里有个Frame组件,用于layout嵌套,可以很好地模块化UI布局。
3. 功能实现
在本案例中,需要实现三个功能,分别是:读取人员名单、随机抽奖以及保存中奖名单。
3.1 读取人员名单
这里采用的是openpyxl读取表格数据并获得某几列的值,由于存在表头,所以最后不需要表头
Python学习交流Q群:906715085### def nameList(window): fileName = values[\'_file\'] try: wb = openpyxl.load_workbook(fileName) active_sheet = wb.active names = [cell_object.value for cell_object in list(active_sheet.columns)[1]][1:] ids = [cell_object.value for cell_object in list(active_sheet.columns)[0]][1:] names = [name+\'_\'+str(id_) for name, id_ in zip(names, ids)] window[\'nameList\'].update(names) return names except: sg.popup(\'请选择正确格式的的人员名单文件\', title=\'提示\',)
3.2. 随机抽奖
由于我们需要一次随机抽取的人数存在多个,所以这里用的是random.sample(),需要注意的是传入的参数中names是需要去掉已
中奖名单
def Result(window, names): global is_run, luckyNames _type = values[\'_type\'] # 本轮奖项类型 _num = int(values[\'_num\']) # 本轮人数 while True: randomName = random.sample(names, k=_num) luckyName = \' \'.join(randomName) window[\'luckyName\'].update(luckyName) if not is_run: headers = [\'奖项\', \'名单\'] toCsv(headers, [_type]*len(randomName), randomName, lucky) luckyNames = luckyNames + _type+\' : \'+luckyName+\'\\n\\n\' window[\'result\'].update(luckyNames) return time.sleep(0.088)
3.3. 保存中奖名单
这里我们用的是csv库的方法,追加存储
def toCsv(headers, col1, col2, file): # 存在则追加,不存在则新建 if os.path.exists(lucky): with open(lucky, \'a\', encoding=\'utf_8_sig\', newline=\'\') as csvfile: writer = csv.writer(csvfile) writer.writerows(zip(col1, col2)) else: with open(lucky, \'w\', encoding=\'utf_8_sig\', newline=\'\') as csvfile: writer = csv.writer(csvfile) writer.writerow(headers) writer.writerows(zip(col1, col2))
完成核心功能函数后,我们再进行GUI交互逻辑的实现。
3.4. GUI交互逻辑
这里有两个全局变量,其中一个用于记录当前抽奖状态,另外一个用于存储当前已经获奖的人员信息。关于交互逻辑的详情,大
家可以结合核心功能需求及以下代码了解。
Python学习交流Q群:906715085### # 初始状态 is_run = False luckyNames = \'\' # 事件循环 while True: event, values = window.read() if event in (None, \'关闭程序\'): break if event == \'_file\': nameList(window) if event == \'开始抽奖\': if is_run: sg.popup(\'抽奖进行中,无需重复操作......\', title=\'提示\') continue try: names = nameList(window) # 人员名单 _num = int(values[\'_num\']) # 本轮人数 lucky = \'中奖名单.csv\' # 中奖名单 if os.path.exists(lucky): with open(\'中奖名单.csv\', \'r\', encoding=\'utf_8_sig\') as f: reader = csv.reader(f) selectedNames = set([i[1] for i in reader][1:]) names_set = set(names)-selectedNames else: names_set = set(names) if len(names_set) >= _num: is_run = True _thread.start_new_thread(Result, (window, names_set)) else: sg.popup( f\'请选择正确本轮抽奖人数(当前 {len(names_set)} 个未中奖人数)\', title=\'提示\') except: sg.popup(\'请选择正确本轮抽奖人数(别超过总人数哦)\', title=\'提示\') elif event == \'结束\': is_run = False elif event == \'重置\': if is_run: sg.popup(\'抽奖进行中,请等待抽奖结束后重置...\', title=\'提示\') continue yes_no = sg.popup_yes_no( \'重置会清楚历史数据,是否执行此操作??\', text_color=\'red\', title=\'提示\') if yes_no == \'Yes\': try: os.remove(lucky) luckyNames = \'\' window[\'result\'].update(luckyNames) window[\'luckyName\'].update(luckyNames) sg.popup(\'抽奖历史记录已被重置......\', title=\'提示\') except: sg.popup(\'无抽奖历史记录......\', title=\'提示\') window.close()
基于此,我们就完成了随机抽奖小工具的制作。
启动页如下:
最后,大家感兴趣就可以将代码打包成exe可执行文件了,我这边打包下来大概10MB左右大小。
以上就是本文全部内容,如果你感兴趣,点个赞和在看支持一下呗。
来源:https://www.cnblogs.com/123456feng/p/16144615.html
本站部分图文来源于网络,如有侵权请联系删除。