Python制作一个随机抽奖小工具的实现


Posted in Python onJuly 07, 2021
目录
  • 1. 核心功能设计
  • 2. GUI设计与实现
  • 3. 功能实现
    • 3.1 读取人员名单
    • 3.2. 随机抽奖
    • 3.3. 保存中奖名单
    • 3.4. GUI交互逻辑

最近在工作中面向社群玩家组织了一场活动,需要进行随机抽奖,参考之前小明大佬的案例,再结合自己的需求,做了一个简单的随机抽奖小工具。

今天我就来顺便介绍一下这个小工具的制作过程吧!

先看效果:

Python制作一个随机抽奖小工具的实现

 

1. 核心功能设计

针对随机抽奖的小工具,需要可以导入参与抽奖的人员名单,然后选择不同的奖励类型进行随机抽取获奖名单并导出。

那么,简单进行需求拆解,大致梳理出以下核心功能:

名单导入

为了避免出现重名情况,这里我们约定以下几点:

①导入参与抽奖的人员名单文件(xlsx类型文件)

②数据第一列为ID,第二列为name

参考格式案例

Python制作一个随机抽奖小工具的实现

奖项类型选择

奖项类型是指一等奖、二等奖这类标识语,这里我们内置了特等奖-六等奖共7个选项供选取

本轮人数

本轮人数是指每次抽奖时一次性抽取的获奖人数,默认值为5

①当填入的数字超过剩余未获奖人数时,会进行提示并显示未获奖人数

②当填入的数字为0表示轮空,也需要手动结束

③当填入的数字为负数时,点击抽奖无响应

④当填入的非数字时,会进行提示需要输入正确数字

抽奖时轮播区域

用于显示抽奖中随机滚动参与本轮抽奖的人员名单

人员名单

当选择正确的人员名单文件后,这里会自动显示人员信息列表

中奖记录

记录每次抽取的奖项类型及获奖名单

开始抽奖

①开始抽奖时,会先判断抽奖设置是否满足条件,否则会有相关提示

②抽奖中点击开始抽奖会提示正在抽奖中

结束

①非抽奖状态下点击结束无响应

②抽奖中点击结束将显示本次抽奖结果

重置

①重置会清掉历史抽奖记录(含本地文件,如有必要建议对中奖名单留档)

②抽奖中点击重置会提示正在抽奖中

③非抽奖状态点击重置会提示该操作会删除历史记录,是否确认

基本功能点确认后,我们就开始进行GUI设计。

 

2. GUI设计与实现

基于功能点,我们用axure简单进行UI布局设计,然后再通过GUI开发库进行设计,这里依旧采用的是pysimplegui,主要是简单方便。

Python制作一个随机抽奖小工具的实现

基于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读取表格数据并获得某几列的值,由于存在表头,所以最后不需要表头

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交互逻辑

这里有两个全局变量,其中一个用于记录当前抽奖状态,另外一个用于存储当前已经获奖的人员信息。关于交互逻辑的详情,大家可以结合核心功能需求及以下代码了解。

# 初始状态
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()

基于此,我们就完成了随机抽奖小工具的制作。

启动页如下:

Python制作一个随机抽奖小工具的实现

最后,大家感兴趣就可以将代码打包成exe可执行文件了,我这边打包下来大概10MB左右大小。

到此这篇关于Python制作一个随机抽奖小工具的实现的文章就介绍到这了,更多相关Python 随机抽奖小工具内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python版的文曲星猜数字游戏代码
Sep 02 Python
解读Python中degrees()方法的使用
May 18 Python
Python设计模式编程中解释器模式的简单程序示例分享
Mar 02 Python
Python使用爬虫爬取静态网页图片的方法详解
Jun 05 Python
解决Pycharm调用Turtle时 窗口一闪而过的问题
Feb 16 Python
Python实用工具FuckIt.py介绍
Jul 02 Python
python 实现12bit灰度图像映射到8bit显示的方法
Jul 08 Python
django 通过url实现简单的权限控制的例子
Aug 16 Python
基于Python实现剪切板实时监控方法解析
Sep 11 Python
在Pytorch中计算自己模型的FLOPs方式
Dec 30 Python
pytorch forward两个参数实例
Jan 17 Python
Python urllib3软件包的使用说明
Nov 18 Python
Python 数据科学 Matplotlib图库详解
Python3中最常用的5种线程锁实例总结
Jul 07 #Python
python实现简单的聊天小程序
python获取对象信息的实例详解
Jul 07 #Python
利用Python判断整数是否是回文数的3种方法总结
Jul 07 #Python
如何利用opencv判断两张图片是否相同详解
Python中文纠错的简单实现
Jul 07 #Python
You might like
又一个php 分页类实现代码
2009/12/03 PHP
php生成动态验证码gif图片
2015/10/19 PHP
PHP+mysql实现从数据库获取下拉树功能示例
2017/01/06 PHP
PHP 文件写入和读取操作实例详解【必看篇】
2019/11/04 PHP
Ext.FormPanel 提交和 Ext.Ajax.request 异步提交函数的区别
2009/11/12 Javascript
Jquery ajax不能解析json对象,报Invalid JSON错误的原因和解决方法
2010/03/27 Javascript
jQuery基础知识filter()和find()实例说明
2010/07/06 Javascript
使用jQuery重置(reset)表单的方法
2014/05/05 Javascript
JavaScript设计模式之代理模式介绍
2014/12/28 Javascript
对比分析AngularJS中的$http.post与jQuery.post的区别
2015/02/27 Javascript
JS触发服务器控件的单击事件(详解)
2016/08/06 Javascript
Bootstrap幻灯片轮播图支持触屏左右手势滑动的实现方法
2016/10/13 Javascript
使用snowfall.jquery.js实现爱心满屏飞的效果
2017/01/05 Javascript
详解Angular2表单-模板驱动的表单(Template-Driven Forms)
2017/08/04 Javascript
layui表格checkbox选择全选样式及功能的实例
2018/03/07 Javascript
vue项目中使用Svg的方法
2018/10/24 Javascript
React Hooks 实现和由来以及解决的问题详解
2020/01/17 Javascript
vue实现扫码功能
2020/01/17 Javascript
[01:06]欢迎来到上海,TI9
2018/08/26 DOTA
python字符串连接的N种方式总结
2014/09/17 Python
python实现带错误处理功能的远程文件读取方法
2015/04/29 Python
Python线性回归实战分析
2018/02/01 Python
python如何定义带参数的装饰器
2018/03/20 Python
解决django前后端分离csrf验证的问题
2019/02/03 Python
使用Python和Scribus创建一个RGB立方体的方法
2019/07/17 Python
HTML5通用接口详解
2016/06/12 HTML / CSS
阿里健康大药房:阿里自营网上药店
2017/08/01 全球购物
Rodd & Gunn澳大利亚官网:新西兰男装品牌
2018/09/25 全球购物
自我鉴定书范文
2013/10/02 职场文书
教学大赛获奖感言
2014/01/15 职场文书
2014年教师学期工作总结
2014/11/08 职场文书
升学宴学生答谢词
2015/01/05 职场文书
法人身份证明书
2015/06/18 职场文书
电工实训心得体会
2016/01/14 职场文书
上手简单,功能强大的Python爬虫框架——feapder
2021/04/27 Python
MYSQL 的10大经典优化案例场景实战
2021/09/14 MySQL