用Python制作一個隨機抽獎小工具

可以叫我才哥 2022-01-15 03:46:45 阅读数:115

python 制作 小工具 小工 工具

大家好,我是才哥。

最近在工作中面向社群玩家組織了一場活動,需要進行隨機抽獎,參考之前小明大佬的案例,再結合自己的需求,做了一個簡單的隨機抽獎小工具。

今天我就來順便介紹一下這個小工具的制作過程吧!

先看效果:

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個微信私聊才哥領取源碼哈!

版权声明:本文为[可以叫我才哥]所创,转载请带上原文链接,感谢。 https://pythonmana.com/2022/01/202201080611485062.html