用Python制作一个随机抽奖小工具

2023-11-17

大家好,我是才哥。

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

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

先看效果:

1. 核心功能设计

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

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

  • 名单导入

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

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

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

参考格式案例

案例

  • 奖项类型选择

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

  • 本轮人数

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

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

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

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

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

  • 抽奖时轮播区域

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

  • 人员名单

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

  • 中奖记录

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

  • 开始抽奖

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

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

  • 结束

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

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

  • 重置

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

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

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

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

2. GUI设计与实现

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

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

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()

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

启动页如下:

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

关于打包操作,大家可以参考《》了解哈。

以上就是本文全部内容,如果你感兴趣,点个赞和在看支持一下呗。

关于小工具可以后台回复955获取,在看达到10个微信私聊才哥领取源码哈!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用Python制作一个随机抽奖小工具 的相关文章

随机推荐

  • C++字符串格式化

    c c 的字符串格式化问题 常常会困扰人 只要做个集中整理 以便今后查看 格式化值 返回百分号 b 返回二进制数 c 返回与ASCII值相对应的字符 d 带有正负号的十进制数 e 科学计数符号 如 1 2e 2 u 不带正负号的十进制数 u
  • js实现打印功能

    window print 执行打印功能 打印后执行的操作window onafterprint 打印前执行的操作window onbeforeprint div class x body div class noprint div type
  • js原型,原型链,call/apply

    目录 1 prototype原型 2 proto 2 1常见错误 3 原型链 3 1 Object prototype是大部分对象的最终原型 3 2 Object create 4 call apply 1 prototype原型 定义 原
  • 新手如何学习网络安全?

    每天都有新闻报道描述着新技术对人们的生活和工作方式带来的巨大乃至压倒性影响 与此同时有关网络攻击和数据泄露的头条新闻也是日益频繁 攻击者可谓无处不在 企业外部充斥着黑客 有组织的犯罪团体以及民族国家网络间谍 他们的能力和蛮横程度正日渐增长
  • topk问题求解

    1 利用快排思路求解 static int partation vector
  • 如何使用ChatGPT制作免费的数字人

    传统的数字人制作过程 制作属于自己的免费的数字人是一个复杂的过程 需要涉及多个方面的知识和技术 以下是一个大致的步骤指南 以帮助你开始这个过程 1 确定数字人的目标和设计 首先 你需要确定数字人的用途和目标 是用于虚拟助手 游戏角色还是其他
  • SpringBoot将文件上传到项目的根路径中,相对路径

    1 依赖
  • DLL调试方法 VS2012 C++ 有代码时

    把exe放到输出目录 并把调试 命令 设为 S o l u t i o n
  • vue 如何在一个页面上调用另一个页面的方法

    vue 如何在一个页面上调用另一个页面的方法 首先同一个vue实例来调用两个方法 所以可以建立一个中转站 建立 util js 中转站文件 任意位置 我是在 assets js util js import Vue from vue exp
  • MySQL基础知识每日总结(5)

    regexp检查总是返回0 没有匹配 或者1 匹配 一 CASE表达式 1 两种写法 简单case表达式 case sex when 1 then 男 when 2 then 女 else 其他 end 搜索case表达式 case whe
  • .sh 文件 注释

    usr bin env bash 不需要寻找程序在系统中的位置 只要程序在 PATH中 根据环境寻找并运行默认的版本 set e exit the script if an error happens MODEL TAR depparse
  • 华为校招机试 - 单词重量(Java)

    题目描述 每个句子由多个单词组成 句子中的每个单词的长度都可能不一样 我们假设每个单词的长度Ni为该单词的重量 你需要做的就是给出整个句子的平均重量V 输入描述 无 输出描述 无 用例 输入 Who Love Solo 输出 3 67 说明
  • 计算机组成原理期末考试题

    计算机组成原理期末考试试题及答案 一 选择题 1 完整的计算机系统应包括 D A 运算器 存储器和控制器 B 外部设备和主机 C 主机和实用程序 D 配套的硬件设备和软件系统 2 计算机系统中的存储器系统是指 D A RAM存储器 B RO
  • 交换机端口安全

    文章目录 一 802 1X认证 1 定义和起源 2 认证方式 本地认证 远程集中认证 3 端口接入控制方式 基于端口认证 基于MAC地址认证 二 端口隔离技术 1 隔离组 2 隔离原理 3 应用场景 首先可以看下思维导图 以便更好的理解接下
  • MinIO文件服务器快速部署和案例演示

    MinIO文件服务器 文章目录 前言 服务器部署 依赖配置 SpringBoot配置 方法模板类 方法使用示例 易错点和注意点 MinIO的文件上传时文件类型设置的坑 前言 这个MinIO服务用起来比较简单 配置和使用都非常快 1 博客案例
  • css设置滚动条样式

    废话不多说 直接上代码 1 设置全局滚动条样式 webkit scrollbar 滚动条整体样式 width 4px 高宽分别对应横竖滚动条的尺寸 height 1px webkit scrollbar thumb 滚动条里面小方块 bor
  • 传智书城项目修改(修改图片、文本),使用eclipse修改, 以及解决出现的乱码问题

    在开始本教程先 请确保已经导入项目并能在网页中显示 导入项目参考http t csdn cn Bl0JX 一 修改首页顶部 首页效果如下 在项目文件中找到head jsp文件 在右侧的布局文件代码中修改首页的文字和首页logo 修改logo
  • weston设置

    weston设置 屏幕旋转180度方法 修改标题栏位置 启动配置文件 屏幕旋转180度方法 编辑 etc xdg weston weston ini文件 增加如下语句 output name DSI 1 transform 180 其中na
  • buuctf-Web1

    在登陆界面用sql注入的各种手段都没用 注册进去看看 抓包后发现数据包有点像xss 也能使它弹窗 但是好像没什么用 用标题1 会有关于sql语句的弹窗 但是如果抓包就不会出现 也能说明是单引号闭合 1 就不行 能知道是sql注入也不容易 闭
  • 用Python制作一个随机抽奖小工具

    大家好 我是才哥 最近在工作中面向社群玩家组织了一场活动 需要进行随机抽奖 参考之前小明大佬的案例 再结合自己的需求 做了一个简单的随机抽奖小工具 今天我就来顺便介绍一下这个小工具的制作过程吧 先看效果 1 核心功能设计 针对随机抽奖的小工