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实现的防DDoS脚本
Feb 08 Python
easy_install python包安装管理工具介绍
Feb 10 Python
python将txt文件读入为np.array的方法
Oct 30 Python
Python查找文件中包含中文的行方法
Dec 19 Python
python遍历小写英文字母的方法
Jan 02 Python
在Pycharm terminal中字体大小设置的方法
Jan 16 Python
Pandas读取并修改excel的示例代码
Feb 17 Python
解决Python计算矩阵乘向量,矩阵乘实数的一些小错误
Aug 26 Python
TensorFlow实现从txt文件读取数据
Feb 05 Python
详解python 支持向量机(SVM)算法
Sep 18 Python
python反爬虫方法的优缺点分析
Nov 25 Python
pytorch分类模型绘制混淆矩阵以及可视化详解
Apr 07 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
《神奇女侠:血脉》神力女超人大战犯罪公司
2020/04/09 欧美动漫
php目录管理函数小结
2008/09/10 PHP
程序员编程十条戒律
2009/07/09 PHP
PHP 万年历实现代码
2012/10/18 PHP
PHP Warning: Module 'modulename' already loaded in问题解决办法
2015/03/16 PHP
PHP中new static()与new self()的比较
2016/08/19 PHP
PHP通过GD库实现验证码功能示例
2019/02/23 PHP
JavaScript 对话框和状态栏使用说明
2009/10/25 Javascript
jquery弹出层类代码分享
2013/12/27 Javascript
js分页代码分享
2014/04/28 Javascript
Jquery中扩展方法extend使用技巧
2014/08/24 Javascript
JavaScript使用setInterval()函数实现简单轮询操作的方法
2015/02/02 Javascript
基于jquery实现页面滚动时顶部导航显示隐藏
2020/04/20 Javascript
JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法
2016/05/19 Javascript
JS获取多维数组中相同键的值实现方法示例
2017/01/06 Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
2017/03/07 Javascript
JavaScript实现计算多边形质心的方法示例
2018/01/31 Javascript
jquery ajax加载数据前台渲染方式 不用for遍历的方法
2018/08/09 jQuery
vue+vue-router转场动画的实例代码
2018/09/01 Javascript
深入学习JavaScript中的bom
2019/05/27 Javascript
javascript for循环性能测试示例
2019/08/07 Javascript
Node.js 中判断一个文件是否存在
2020/08/24 Javascript
python实现聚类算法原理
2018/02/12 Python
利用Python正则表达式过滤敏感词的方法
2019/01/21 Python
Pytorch之Variable的用法
2019/12/31 Python
Python如何实现定时器功能
2020/05/28 Python
TripAdvisor台湾:全球最大旅游网站
2018/08/26 全球购物
简述DNS进行域名解析的过程
2013/12/02 面试题
绩效专员岗位职责
2013/12/02 职场文书
教师党员公开承诺事项
2014/05/28 职场文书
2014年班务工作总结
2014/12/02 职场文书
幼儿园中秋节活动总结
2015/03/23 职场文书
运动员加油词
2015/07/18 职场文书
Python基础之pandas数据合并
2021/04/27 Python
详解CSS故障艺术
2021/05/25 HTML / CSS
Apache Hudi数据布局黑科技降低一半查询时间
2022/03/31 Servers