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基于scrapy采集数据时使用代理服务器的方法
Apr 16 Python
浅谈Python中chr、unichr、ord字符函数之间的对比
Jun 16 Python
Python虚拟环境virtualenv的安装与使用详解
May 28 Python
Python编程实现的简单神经网络算法示例
Jan 26 Python
python生成器,可迭代对象,迭代器区别和联系
Feb 04 Python
Python实现ping指定IP的示例
Jun 04 Python
Python使用线程来接收串口数据的示例
Jul 02 Python
python中的列表与元组的使用
Aug 08 Python
pytorch在fintune时将sequential中的层输出方法,以vgg为例
Aug 20 Python
浅析Python语言自带的数据结构有哪些
Aug 27 Python
Python figure参数及subplot子图绘制代码
Apr 18 Python
python反爬虫方法的优缺点分析
Nov 25 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
web方式ftp
2006/10/09 PHP
用来解析.htgroup文件的PHP类
2012/09/05 PHP
基于PHP+Ajax实现表单验证的详解
2013/06/25 PHP
FastCGI 进程意外退出造成500错误
2015/07/26 PHP
php实现常见图片格式的水印和缩略图制作(面向对象)
2016/06/15 PHP
简单的JS多重继承示例
2008/03/13 Javascript
Jquery 表单取值赋值的一些基本操作
2009/10/11 Javascript
JQuery的Alert消息框插件使用介绍
2010/10/09 Javascript
Ajax搜索结果页面下方的分页按钮的生成
2012/04/05 Javascript
js实现图片拖动改变顺序附图
2014/05/13 Javascript
JQuery中DOM事件合成用法实例分析
2015/06/13 Javascript
javascript设计模式之对象工厂函数与构造函数详解
2015/07/30 Javascript
javascript同步服务器时间和同步倒计时小技巧
2015/09/24 Javascript
自己动手写的javascript前端等待控件
2015/10/30 Javascript
Web前端新人笔记之jquery入门心得(新手必看)
2016/05/17 Javascript
AngularJS基础 ng-switch 指令简单示例
2016/08/03 Javascript
seajs学习教程之基础篇
2016/10/20 Javascript
JavaScript异步上传图片文件的实例代码
2017/07/04 Javascript
form表单序列化详解(推荐)
2017/08/15 Javascript
JS扩展String.prototype.format字符串拼接的功能
2018/03/09 Javascript
微信小程序中使用ECharts 异步加载数据的方法
2018/06/27 Javascript
vue-cli创建的项目中的gitHooks原理解析
2020/02/14 Javascript
js实现的订阅发布者模式简单示例
2020/03/14 Javascript
python里使用正则的findall函数的实例详解
2017/10/19 Python
pandas.DataFrame 根据条件新建列并赋值的方法
2018/04/08 Python
Python 限制线程的最大数量的方法(Semaphore)
2019/02/22 Python
python实现替换word中的关键文字(使用通配符)
2020/02/13 Python
使用python 计算百分位数实现数据分箱代码
2020/03/03 Python
长青弘远的面试题
2012/06/09 面试题
大学生个人简历中的自我评价
2013/12/27 职场文书
党员四风自我剖析材料
2014/10/07 职场文书
党员学习新党章思想汇报
2014/10/25 职场文书
2015年收银工作总结范文
2015/04/01 职场文书
诚信考试主题班会
2015/08/17 职场文书
《赵州桥》教学反思
2016/02/17 职场文书
德劲DE1105机评
2022/04/05 无线电