使用Python实现多功能课堂点名器与抽签工具
作者:PythonFun
一、问题缘起
去年,ChatGPT浪潮袭来,我懂简单的Python基础语法,又有一些点子,于是借助于人工智能问答工具,一步一步地制作了一个点名器,也可以用于抽签。当时,我已经设计好页面和基础的功能,并在广大网友中开启了测试。
点名器1.0
目前,写的这个点名器的文章阅读里已经达到了近700次,而且有6个人收藏,这说明很多人还是挺需要这样的点名器的。不过,也有网友给我留言,提出了修改的建议,如点名器这个界面有点儿大,教学过程中有时用到,有时用不到,用到时可以展示,不用时,能不能把这个界面最小化到右上角,再点右上角把它调出来。
还有人说,如果抽到这个人,能不能把名字也读出来,这样就不用老师再说他们的名字了。听到声音,看到自己的名字,学生就可以站起来直接回答问题了,老师也不必再念学生名字了。
顺便说一下:当时,我刚自学Python,主要是看董付国的书,讲的通俗易懂,内容也很丰富,重要的知识点都讲到了。我看的就是下面这本书:
只是懂一些基本的语法,但是在人工智能的加持下,我很快就学会了自主编程。
之前,一直忙其它的事情,没有抽出时间来,现在我用了ChatGPT的帮助,相信利用Python做一些小项目的开发都不是难事。
二、开发过程
1. 为点名器添加最大化、最小化功能
首先,我对原有点名器的改造与升级都是基于第一个版本,我需要添加的是朗读、最小化这两个功能。
向ChatGPT提问
ChatGPT根据我的请求,很快给出了相应的代码:
import tkinter as tk class MinimizeApp: def __init__(self, master): self.master = master self.master.geometry("800x600") # 初始大小 self.minimized = False # 标记是否已最小化 self.original_geometry = '' # 存储原始窗口大小 # 最小化/最大化按钮 self.toggle_btn = tk.Button(master, text="最小化", command=self.toggle) self.toggle_btn.pack() # 配置最小化时显示的小窗口 self.mini_window = tk.Toplevel(self.master) self.mini_window.geometry("100x50+{}+0".format(self.master.winfo_screenwidth() - 100)) self.mini_window.overrideredirect(True) # 去除窗口边框 self.mini_window.withdraw() # 初始时隐藏 # 最大化按钮 self.maximize_btn = tk.Button(self.mini_window, text="最大化", command=self.toggle) self.maximize_btn.pack(fill=tk.BOTH, expand=True) def toggle(self): if self.minimized: # 如果当前是最小化,恢复窗口 self.master.deiconify() # 显示主窗口 self.master.geometry(self.original_geometry) # 恢复原始大小 self.mini_window.withdraw() # 隐藏最小化窗口 self.toggle_btn.config(text="最小化") self.minimized = False else: # 如果当前是正常大小,最小化窗口 self.original_geometry = self.master.geometry() # 存储当前大小和位置 self.master.withdraw() # 隐藏主窗口 self.mini_window.deiconify() # 显示最小化窗口 self.minimized = True def main(): root = tk.Tk() app = MinimizeApp(root) root.mainloop() if __name__ == "__main__": main()
上面的代码可以实现一个自定义的最小化/最大化功能,首先创建一个最小化按钮,当用户点击这个按钮时,整个应用窗口缩小至屏幕的右上角,并只显示一个最大化按钮。再次点击这个最大化按钮时,窗口恢复到其原始大小。
我们通过手动点击的方式,管理窗口的大小和位置,以及按钮的显示和隐藏。
下一步是把以上代码,融入到点名器1.0当中,我们需要对这里的按纽对象名称进行修改,删除与旧版相比重复的代码,同时还要修复调试过程中的报错。
上课过程中,我又进行了实地的测试,发现最小化后窗品没有置于所有窗口的最前方,于是,我于向ChatGPT发问,如果设置最小化窗口前端显示,它很快给了我下面的代码:
self.mini_window.attributes('-topmost', 1)
果然,通过这个代码,前置显示问题很快解决了。
2. 为点名器添加朗读功能
增加了最大最小化窗口的功能,我还想让点名器自动朗读出点名器上的人名,这样显示的名字和朗读的声音匹配起来,可以最大可能地节省老师的时间和体力,进一步提升讲课的效率。
为了使软件可以发声,我们需要导入一个pyttsx3这个包,同时还要保证软件联网。
当滚动到显示的人名时,就会触发朗读的功能。当然,也有人不想使用朗读的功能,或者使用的电脑无法上网,这时我们就需要增加一个复选框,用复选框来控制是否朗读发声。
我能过向ChatGPT提问得到了如下回复:
增加复选框
接下来,我要做的是,在def __init__(self, master)这个初始化函数里,加上一个复选框代码,同时通过检测复选 框check_var的值,来控制是否朗读发声。注意这里的复选框不需要定义命令函数。
最后,在测试时,我发现软件不朗读人名,后来才发现self.engine = pyttsx3.init()这个发声引擎的初始化要在软件界面初始化前启动。
3. 软件使用展示
经过中午和下午的修改测试,终于完成了新版点名器的雏形,如下图所示:
4. 优化后代码
在增加朗读、最小化等功能同时,我征求网友的意见,又增加了姓名字体的自动调节功能。而且,为了让界面显示的更好看,我把按纽居中显示,最后形成以下软件。
软件代码如下:
# 2023年4月10日更新1. 修复按纽点击开始再点击暂停2. 增加标记功能 3.增加欢迎页 4.改变播放速度 # 2024年2月28日更新1. 增加人名朗读 2. 增加窗口最小化功能 3. 按纽居中 4. 字体大小控制 import tkinter as tk from tkinter import messagebox from tkinter import ttk import os import random import time import pyttsx3 class RollCallApp: def __init__(self, master): self.engine = pyttsx3.init() self.master = master self.master.title("点名器 Gordon QQ:403096966") #self.master.resizable(False, False) #self.master.geometry("880x300") # 初始大小 self.minimized = False # 标记是否已最小化 self.master.protocol("WM_DELETE_WINDOW", self.display_messagebox) # 弹窗提示确认退出 self.master.attributes('-topmost', True) # 读取文件中的名字 self.names = [] self.load_names() # 播放名字的控件 self.label_name = tk.Label(self.master, text="欢迎使用点名器", font=("Times New Roman", 90), fg="blue") self.label_name.pack(pady=50) #设置frame 居中显示 button_frame = tk.Frame(self.master) button_frame.pack() items = ("加分","旷课", "迟到", "请假") self.combo = ttk.Combobox(button_frame, values=items, font=("宋体", 20),width=5) self.combo.set("加分") # 设置默认值 self.combo.configure(font=("宋体", 20)) #设置字体大小写 self.scale = tk.Scale(self.master, from_ = 30, to = 210, orient = 'horizontal',command = self.resize) self.scale.set(80) self.scale.pack(expand=True, fill=tk.BOTH,side=tk.BOTTOM) # 设置退出按钮 self.button_quit = tk.Button(button_frame, text="退出", font=("宋体", 20), width=9, command=self.display_messagebox) self.button_quit.pack(side=tk.LEFT,anchor="center",padx=22) # 设置标记内容 self.combo.pack(side=tk.LEFT, fill=tk.BOTH, padx=5) # 创建一个IntVar对象来存储复选框的状态 self.check_var = tk.IntVar(value=0) # 默认值设置为0(未选中) # 控制按钮 self.button_mark = tk.Button(button_frame, text="标记", font=("宋体", 20), width=9, command=self.write_txt) self.button_mark.pack(side=tk.LEFT,anchor="center",padx=20) # 创建复选框,绑定到check_var变量 self.checkbox = tk.Checkbutton(button_frame, text="发声", font=("宋体", 12), variable=self.check_var) self.checkbox.pack(side=tk.LEFT,anchor="center", padx=3) # 控制按钮 self.button_action = tk.Button(button_frame, text="开始", font=("宋体", 20), width=9, command=self.toggle_rolling) self.button_action.pack(side=tk.LEFT, anchor="center",padx=20) self.button_min = tk.Button(button_frame, text="最小化", font=("宋体", 20), width=9, command=self.toggle) self.button_min.pack(side=tk.LEFT,anchor="center", padx=20) # 配置最小化时显示的小窗口 self.mini_window = tk.Toplevel(self.master) self.mini_window.geometry("100x50+{}+0".format(self.master.winfo_screenwidth() - 100)) self.mini_window.overrideredirect(True) # 去除窗口边框 self.mini_window.withdraw() # 初始时隐藏 # 最大化按钮 self.maximize_btn = tk.Button(self.mini_window, text="最大化",font=("宋体", 15, "bold"), command=self.toggle) self.maximize_btn.pack(fill=tk.BOTH, expand=True) # 控制变量 self.rolling = False self.current_name = "" #设置引擎 self.engine.setProperty('language', 'zh-CN') rate = self.engine.getProperty('rate') self.engine.setProperty('rate', rate - 50) # 设置发音大小,范围为0.0-1.0 volume = self.engine.getProperty('volume') self.engine.setProperty('volume', 1.2) # 设置默认的声音:voices[0].id代表男生,voices[1].id代表女生 voices = self.engine.getProperty('voices') self.engine.setProperty('voice', voices[0].id) def resize(self,ev = None): # 监控窗口是不是最大化,最大化则字体变大,否则为55号字 if self.master.state() == 'zoomed': self.label_name.config(font = '宋体 -%d bold' % self.scale.get()) elif not self.master.state() == 'zoomed':#self.root.state() == 'iconic': self.label_name.config(font = '宋体 -%d bold' % self.scale.get()) def toggle(self): if self.minimized: # 如果当前是最小化,恢复窗口 self.master.deiconify() # 显示主窗口 #self.master.geometry("880x300") # 初始大小 #self.master.geometry(self.original_geometry) # 恢复原始大小 self.mini_window.withdraw() # 隐藏最小化窗口 self.button_min.config(text="最小化") self.minimized = False else: # 如果当前是正常大小,最小化窗口 self.original_geometry = self.master.geometry() # 存储当前大小和位置 self.master.withdraw() # 隐藏主窗口 self.mini_window.deiconify() # 显示最小化窗口 self.mini_window.attributes('-topmost', 1) self.minimized = True def load_names(self): """从当前目录下的names.txt文件中读取名字""" if os.path.exists("names.txt"): with open("names.txt", "r", encoding="utf-8") as f: for name in f: name = name.strip() if name: self.names.append(name) else: messagebox.showerror("错误","找不到names.txt,请把人名放到当前目录下的names.txt中!") with open("names.txt", "w+", encoding="utf-8") as fi: fi.write("") def write_txt(self): label_text = self.label_name.cget("text") with open("标记内容.txt",'a+',encoding='utf-8') as f: f.write(label_text + f" {self.combo.get()}\n") def toggle_rolling(self): """切换播放状态,并更新按钮文字""" self.rolling = not self.rolling if self.rolling: self.button_action.config(text="暂停") self.roll_name() if self.check_var.get() == 1: self.engine.say(self.current_name) self.engine.runAndWait() else: self.button_action.config(text="开始") def roll_name(self): """随机选取一个名字播放""" if self.names: self.current_name = random.choice(self.names) self.label_name.config(text=self.current_name) self.master.update() time.sleep(0.01) if self.rolling: self.roll_name() def display_messagebox(self): """弹窗提示是否确认退出程序""" if messagebox.askokcancel("退出程序", "确定要退出程序吗?"): self.master.destroy() if __name__ == "__main__": root = tk.Tk() app = RollCallApp(root) root.mainloop()
三、学后反思
本软件最初编写于去年的四月份,今年的二月突然有了新的灵感,短时间内增加了二个不错的功能。看来软件的编写也是需要一定时间的打磨。在汲取用户意见的同时,还要利用ChatGPT对原有的软件进行改造升级。
Python是当下最热门的编程语言,在人工智能领域发挥着不可替代的作用。它的扩展性、灵活性极强,可以实现跨平台的应用,被广泛应用于Web开发、网络爬虫、办公自动化等领域。因此,为自己的工作和生活带来极大的便利,我建议大家尽早学习这门流行的语言。在ChatGPT的赋能下,每个人都可以借用于视频、书本轻松学会它。
以上就是使用Python实现多功能课堂点名器与抽签工具的详细内容,更多关于Python点名器的资料请关注脚本之家其它相关文章!