在如今这个高速发展的时代,年底的抽奖是每个公司不可或缺的环节。每到年底,抽奖这个话题很多人都会讨论,都希望自己可以中奖。很多公司每年为了实现公平抽奖,往往需要投入大量时间和精力。在AI技术日益成熟的今天,我们完全可以使用Python的Tkinter库实现一个简单的年会抽奖程序。Tkinter库是Python的GUI(图形用户界面)标准库,它的功能强大,允许我们创建复杂的窗口、按钮、输入框等控件。本节教程将介绍如何使用Tkinter库设计一个有趣且实用的年会抽奖程序。
1、抽奖程序介绍
假设某公司有2000名员工,年会抽奖的奖项设定如下:
特等奖1名:一台笔记本电脑
一等奖2名:一台液晶电视机
二等奖5名:一部手机
三等奖10名:一个电动剃须刀
四等奖50名:一个保温杯
鼓励奖100名:一包抽纸
抽奖规则:
-
共抽6次,第一次抽特等奖,第二次抽一等奖,第三次抽二等奖,以此类推。
-
每个员工只有一次中奖机会,不得重复中奖。
首先,打开抽奖程序,在输入框中输入所有的抽奖名单,注意,必须每行一个名字。接着使用random模块进行随机抽取。最后,通过Tkinter库的ScrolledText控件一次性输出抽奖结果。 其中,random模块是实现抽奖功能的核心,该模块提供了生成随机数和从序列中随机选择元素的函数。
该抽奖程序主要包括两个核心窗口页面,分别是抽奖的主窗口和奖项设置窗口,在Tkinter应用程序的主窗口里,可以通过“设置奖项”按钮打开奖项设置窗口,在弹出的输入框中自定义输入“奖项名称”和“获奖人数”,比如,特等奖设定1名,一等奖设定2名,以此类推。每抽奖一次,剩余名单中将删除已中奖名单,确保不重复中奖。
2、抽奖程序界面演示
3、代码实现
(1)导入必要的库
import random, webbrowser
import tkinter as tk
from tkinter import scrolledtext, messagebox, filedialog
import tkinter.font as tkFont
这里导入了Tkinter库用于创建GUI应用图形界面,Tkinter的messagebox用于消息提示,scrolledtext用于创建带有滚动条的文本框控件,Tkinter的filedialog模块提供了一个简单的对话框界面,可以让用户选择文件或文件夹。random库Python的一个标准库,用于生成随机数、随机整数、还可以从序列中随机选择数据,random库适用于随机性的运用场景,如模拟、游戏开发、算法测试等。Python的webbrowser库能够调用系统的默认浏览器或指定浏览器,打开指定的URL或本地的HTML文件。
(2)抽奖程序的完整代码如下所示:
动手练一练:
import random, webbrowser
import tkinter as tk
from tkinter import scrolledtext, messagebox, filedialog
import tkinter.font as tkFont
# 定义PrizeDraw类
class PrizeDraw:
def __init__(self, members, prizes):
# 初始化抽奖系统
# 获取成员名单
self.members = members.copy()
# 奖项设置,prizes是字典,格式为 {奖项名称: 奖品数量}
self.prizes = prizes
# 定义空字典,用于存储中奖记录
self.winners = {}
# 定义一轮抽奖函数
def draw(self, award_name):
# 判断奖项名称是否存在
if award_name not in self.prizes:
raise ValueError(f"未找到奖项:{award_name}")
# 根据奖项名称获取奖品数量
winners_number = self.prizes[award_name]
# 如果奖品数量大于成员数量,则抛出错误
if winners_number > len(self.members):
raise ValueError(f"奖品数量({winners_number})超过剩余参与人数({len(self.members)})")
# 中奖者初始定义为空
winners = []
# 追加中奖者名单
for i in range(winners_number):
winner = random.choice(self.members)
winners.append(winner)
# 剩余名单中删除已中奖名单,确保不重复中奖
self.members.remove(winner)
self.winners[award_name] = winners
# 返回本轮中奖者名单
return winners
# 输出所有中奖结果
def display_results(self):
# 设置允许修改输出框
result_name.config(state=tk.NORMAL)
result_name.insert(tk.END, f"========= 抽奖结果 =========" + "\n")
for prize, winners in self.winners.items():
result_name.insert(tk.END, f"{prize}获得者:" + "\n")
for winner in winners:
result_name.insert(tk.END, f"{winner}" + "\n")
# 抽奖主函数
def main():
# 判断是否已经设置奖项
if not awards:
messagebox.showerror('错误','当前奖项:未设置')
return
# 获取所有名字
members = names_text.get("1.0", "end-1c").strip().split("\n")
# 判断是否为空
if len(members) < 1:
messagebox.showerror("错误", "请输入至少一个名字!")
return
# 将awards列表字典转换成字典形式,格式为 {奖项名称: 奖品数量}
prizes = {item['name']: item['quota'] for item in awards}
# 创建抽奖系统
prize_draw = PrizeDraw(members, prizes)
# 遍历所有奖项,按顺序抽奖
try:
for key in prizes:
prize_draw.draw(key)
# 最终显示结果
prize_draw.display_results()
except Exception as e:
messagebox.showerror("错误", f"抽奖过程出错:{str(e)}")
# “奖项”设置窗口
def manage_awards():
award_window = tk.Toplevel(app)
award_window.title("奖项管理")
# 设置窗口居中
window_width = 400
window_height = 380
screen_width = award_window.winfo_screenwidth()
screen_height = award_window.winfo_screenheight()
x = (screen_width - window_width) / 2
y = (screen_height - window_height) / 2
award_window.geometry('%dx%d+%d+%d' % (window_width, window_height, x, y))
award_window.resizable(width=False, height=False)
# 创建“奖项名称”和“获奖人数”输入框,完全可以自定义输入
tk.Label(award_window, text="奖项名称:").grid(row=0, column=0, padx=10, pady=10, sticky="e")
name_entry = tk.Entry(award_window)
name_entry.grid(row=0, column=1, padx=10, pady=10, sticky="w")
tk.Label(award_window, text="获奖人数:").grid(row=1, column=0, padx=10, pady=10, sticky="e")
count_entry = tk.Entry(award_window)
count_entry.grid(row=1, column=1, padx=10, pady=10, sticky="w")
# 将“奖项名称”和“获奖人数”追加到awards列表字典中
def prize_add():
name = name_entry.get().strip()
counts = count_entry.get().strip()
if not name:
messagebox.showerror("错误", "奖项名称不能为空")
return
try:
count = int(counts)
if count <= 0:
raise ValueError
except ValueError:
messagebox.showerror("错误", "请输入有效的正整数")
return
if any(award["name"] == name for award in awards):
messagebox.showerror("错误", "该奖项名称已存在")
return
awards.append({
"name": name,
"quota": count,
})
update_listbox()
name_entry.delete(0, tk.END)
count_entry.delete(0, tk.END)
# 删除已设定的“奖项名称”和“获奖人数”
def delete_award():
selected = listbox.curselection()
if not selected:
messagebox.showwarning("警告", "请先选择奖项再删除")
return
index = selected[0]
del awards[index]
update_listbox()
# 定义退出函数
def user_quit():
award_window.destroy()
add_btn = tk.Button(award_window, text="添加奖项并保存", command=prize_add)
add_btn.grid(row=2, columnspan=2, padx=10, pady=10)
listbox = tk.Listbox(award_window, width=50)
listbox.grid(row=3, columnspan=2, padx=10, pady=5)
del_btn = tk.Button(award_window, text="删除选中奖项", command=delete_award)
del_btn.grid(row=4, column=0, padx=10, pady=5, sticky="e")
# 创建“确认设置”按钮
quit_button = tk.Button(award_window,text='确认设置', command=user_quit)
quit_button.grid(row=4, column=1, padx=10, pady=5)
# 将已设置的结果追加到listbox控件中显示
def update_listbox():
listbox.delete(0, tk.END)
for award in awards:
listbox.insert(tk.END, f"{award['name']} - {award['quota']}人")
update_listbox()
award_window.transient(app)
award_window.grab_set()
app.wait_window(award_window)
# 保存抽奖结果到本地的txt文件内
def save_result():
# 创建一个文件对话框来选择文件保存的位置
save_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files", "*.txt")])
if save_path:
# 获取ScrolledText的内容
content = result_name.get(1.0, tk.END)
# 写入文件
with open(save_path, "w") as file:
file.write(content)
# 清除所有的抽奖结果
def clear_result():
# 允许修改输出框
result_name.config(state=tk.NORMAL)
# 定义清除文本的功能
result_name.delete(1.0, tk.END)
# 设置页面的复位函数
def reset_setting_command():
# 清空名单
names_text.delete("1.0", tk.END)
# 清空“奖项”设置
awards.clear()
clear_result()
# 程序讲解页面
def help_window():
webbrowser.open("https://www.pyhint.com/article/151.html")
# 关于程序页面
def program_about():
about = tk.Tk()
about.title('关于程序')
# 设置窗口居中
window_width = 320
window_height = 320
screen_width = about.winfo_screenwidth()
screen_height = about.winfo_screenheight()
x = (screen_width - window_width) / 2
y = (screen_height - window_height) / 2
about.geometry('%dx%d+%d+%d' % (window_width, window_height, x, y))
about.resizable(width=False, height=False)
about_frame = tk.Frame(about, width=320, height=320)
about_frame.pack()
about_font_1 = tkFont.Font(family='宋体', size=16, weight=tkFont.BOLD)
tk.Label(about_frame, text='抽奖系统', font=about_font_1).place(x=120, y=20)
tk.Label(about_frame, text='使用编程语言:Python', font=about_font_1).place(x=50, y=90)
tk.Label(about_frame, text='导入名单方式:直接输入名单', font=about_font_1).place(x=50, y=150)
tk.Label(about_frame, text='保存中奖名单方式:txt文件保存', font=about_font_1).place(x=50, y=210)
tk.Label(about_frame, text='创作者:www.pyhint.com', font=about_font_1).place(x=50, y=270)
about.mainloop()
# 当前模块直接被执行
if __name__ == "__main__":
# 创建Tkinter窗口
app = tk.Tk()
app.title("抽奖工具")
menu_bar = tk.Menu(app)
file_menu = tk.Menu(menu_bar, tearoff=0)
file_menu.add_command(label="关于程序", command=program_about)
file_menu.add_command(label="程序讲解", command=help_window)
file_menu.add_separator()
file_menu.add_command(label="退出", command=app.quit)
menu_bar.add_cascade(label="帮助", menu=file_menu)
settings_menu = tk.Menu(menu_bar, tearoff=0)
settings_menu.add_command(label="管理奖项", command=manage_awards)
settings_menu.add_command(label="复位", command=reset_setting_command)
menu_bar.add_cascade(label="设置", menu=settings_menu)
app.config(menu=menu_bar)
awards = []
# 设置窗口居中
window_width = 400
window_height = 620
screen_width = app.winfo_screenwidth()
screen_height = app.winfo_screenheight()
x = (screen_width - window_width) / 2
y = (screen_height - window_height) / 2
app.geometry('%dx%d+%d+%d' % (window_width, window_height, x, y))
app.resizable(width=False, height=False)
# 创建抽奖名单输入框
all_label = tk.Label(app, text="请输入抽奖名单,每行一个名字:")
all_label.pack(pady=5)
names_text = scrolledtext.ScrolledText(app, width=50, height=15)
names_text.pack(pady=5)
# 在ScrolledText控件中插入默认文本
names_text.insert(tk.END, "张三\n李四\n王五\n赵六\n钱七\n孙八\n周九\n吴十")
# 创建按钮容器
Button_frame = tk.Frame(app)
Button_frame.pack(pady=5)
# 创建“设置奖项”按钮
settings_Button = tk.Button(Button_frame, text="设置奖项", font=('黑体', 15), command=manage_awards, width=10, height=1)
settings_Button.pack(padx=10, pady=10, side=tk.LEFT)
# 创建“开始抽奖”按钮
confirm_button = tk.Button(Button_frame, text="开始抽奖", font=('黑体', 15), command=main, width=10, height=1)
confirm_button.pack(padx=10, pady=10, side=tk.RIGHT)
# 创建“抽奖结果”输出框
result_label = tk.Label(app, text="抽奖结果:")
result_label.pack(pady=5)
result_name = scrolledtext.ScrolledText(app, width=50, height=15, wrap=tk.WORD, state=tk.DISABLED)
result_name.pack(pady=5)
# 创建按钮容器
result_frame = tk.Frame(app)
result_frame.pack(pady=5)
# 左边创建一个按钮来触发“保存抽奖结果”操作
save_button = tk.Button(result_frame, text="保存抽奖结果", font=('黑体', 15), command=save_result, width=15, height=1)
save_button.pack(padx=10, pady=10, side=tk.LEFT)
# 右边创建“清除抽奖结果”按钮并绑定到clear_result函数
clear_button = tk.Button(result_frame, text="清除抽奖结果", font=('黑体', 15), command=clear_result, width=15, height=1)
clear_button.pack(padx=10, pady=10, side=tk.RIGHT)
# 开启主循环,让窗口处于显示状态
app.mainloop()