基本信息
源码名称:教师考勤和提问系统
源码大小:0.98M
文件格式:.zip
开发语言:Python
更新时间:2026-04-05
   友情提示:(无需注册或充值,赞助后即可获取资源下载链接)

     嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):78630559

本次赞助数额为: 2 元 
   源码介绍
此系统可以对学生进行考勤,对学生进行随机提问,并根据回答情况给分。

import tkinter as tk
import tkinter.font
from tkinter import ttk,messagebox
import taDB,mdfStudentUI,mdfCourseUI,attdSetup,pyttsx3,random,threading,configparser,cmm
import time
from datetime import datetime
import sttUI,os
from playsound import playsound
#Auto-generated by the system. Do NOT modify the makeGUI() function arbitrarily--------Do not delete this line-------------
class mainUI:
    def __init__(self,root):
        self.makeGUI(root)
        self.stdNum=''  #点名提问的学生学号
        self.lstTV=[]  #视图iid列表
        root.protocol('WM_DELETE_WINDOW',self.exit)   
        self.Combobox_12['values']=taDB.getTerm()  #设置系名的学生
        tHead=['序号',"学号","姓名","考勤","提问次数","回答成绩"]  #表头的学生
        tWeight=[40,110,80,40,70,70]   #列宽E_WINDOW',self.exit)   
        self.Combobox_12['values']=taDB.getTerm()  #设置系名的学生
        tHead=['序号',"学号","姓名","考勤","提问次数","回答成绩"]  #表头的学生
        tWeight=[40,110,80,40,70,70]   #列宽
        style = ttk.Style()
        style.theme_use("default")  #样式
        #TreeView_21 = tkinter.ttk.Treeview(Form_1,columns=tHead,show="headings",height=10)
        self.Treeview_5['columns']=tHead
        style.configure('Treeview.Heading',font=('微软雅黑',11))  #设置表头
        style.configure('Treeview',rowheight=25,font=('微软雅黑',11))  #设置表中字体、行高
        style.map('Treeview',
             background=[elm for elm in style.map('Treeview',query_opt='background') if elm[:2]!=('!disabled','!selected')])                  
        self.Treeview_5.tag_configure('evenColor',background='#ccebf6')    #定义偶数行色
        self.Scrollbar_7.config(command = self.Treeview_5.yview)
        self.Treeview_5.config(yscrollcommand = self.Scrollbar_7.set)   
        self.Scrollbar_6.config(command = self.Treeview_5.xview)
        self.Treeview_5.config(xscrollcommand = self.Scrollbar_6.set)  
        self.Treeview_5.bind("<3>",lambda e:rightMenu(e))   #右击弹出菜单      
        for i in range(len(tHead)):  
            self.Treeview_5.heading(column=tHead[i],text=tHead[i],anchor='center')  #定义表头,居中
            self.Treeview_5.column(tHead[i],width=tWeight[i],anchor='w',stretch=1)   #定义列,左对齐
        cfgParser=configparser.ConfigParser()  # 创建一个ConfigParser对象
        cfgParser.optionxform = str          # 保持大小写 
        cmm.cfgParser=cfgParser       
        cfgParser.read(f"{cmm.bPath}default.ini", encoding="utf-8-sig") # 读取配置文件,windows用utf-8-sig
        cmm.restT=int(cfgParser['default']['restT']) #读名间隔
        cmm.firstWeek=cfgParser['default']['firstWeek']   #第1周日期
        cmm.timeWr=cfgParser['default']['timeWr']   #上次写入时间           
        root.title(f'课堂助手 {dateNow} 第{cmm.thisWeek()}周')
        stylePb =ttk.Style()# 创建自定义样式
        stylePb.configure('TProgressbar', background='lime')  #lime是闪光绿   
        stylePb.configure('TProgressbar', thickness=5)  # 像素级“厚度” 
        self.intVar = tk.IntVar(value=1)        
        self.Radiobutton_37.config(variable=self.intVar,value=1)
        self.Radiobutton_38.config(variable=self.intVar,value=2)
        self.intVar2 = tk.IntVar()        
        self.Radiobutton_40.config(variable=self.intVar2,value=1)
        self.Radiobutton_41.config(variable=self.intVar2,value=2)
        self.Radiobutton_43.config(variable=self.intVar2,value=3)
        self.Radiobutton_44.config(variable=self.intVar2,value=4)
        self.Radiobutton_46.config(variable=self.intVar2,value=5)
        lst=[]
        for filename in os.listdir(f'{cmm.bPath}music'):  # 遍历文件夹,获取前奏mp3文件名
           file_path = os.path.join(f'{cmm.bPath}music', filename)
           if os.path.isfile(file_path): lst.append(filename) # 只添加文件(排除子文件夹)               
        self.Combobox_49['values']=lst
        self.Combobox_49.current(0)
        self.Scrollbar_58['command'] = self.Listbox_57.yview
        self.Listbox_57['yscrollcommand']= self.Scrollbar_58.set 
        tpl=('完全正确','恭喜你,答对了','哇,你真厉害','你真是才思敏捷,聪明过人','你真是冰雪聪明',
        '你的想法很有创意','回答比标准答案还精彩'
        ,'你对知识的理解很透彻,逻辑思维能力也很强')
        for it in tpl: self.Listbox_57.insert('end',it)
    def makeGUI(self,root):
        self.LabelFrame_22=tk.LabelFrame(root,text='考勤',width=8,height=1,background='#e0e0e0')
        self.LabelFrame_22.grid(row=1,column=1,sticky='nesw',padx=(5,5))
        self.Frame_10=tk.Frame(root,width=8,height=1)
        self.Frame_10.grid(row=0,column=1,columnspan=3,sticky='we',ipadx=1,ipady=1)
        self.Label_11=tk.Label(self.Frame_10,text='学期',width=3,height=1,anchor='w')
        self.Label_11.pack(side='left',padx=(5,0),pady=(2,0),ipadx=1,ipady=1)
        self.Combobox_12=ttk.Combobox(self.Frame_10,width=10,state='readonly')
        self.Combobox_12.bind("<<ComboboxSelected>>",lambda event:self.Combobox_12_ComboboxSelected(event))
        self.Combobox_12.pack(side='left',padx=2,pady=(2,0),ipadx=0,ipady=1)
        self.Label_13=tk.Label(self.Frame_10,text='班级',width=3,height=1,anchor='w')
        self.Label_13.pack(side='left',padx=(10,0),pady=(2,0),ipadx=1,ipady=1)
        self.Combobox_14=ttk.Combobox(self.Frame_10,width=8,state='readonly')
        self.Combobox_14.bind("<<ComboboxSelected>>",lambda event:self.Combobox_14_ComboboxSelected(event))
        self.Combobox_14.pack(side='left',padx=2,pady=(2,0),ipadx=1,ipady=1)
        self.Label_20=tk.Label(self.Frame_10,text='课程',width=3,height=1)
        self.Label_20.pack(side='left',padx=(10,0),pady=(2,0),ipadx=1,ipady=1)
        self.Combobox_21=ttk.Combobox(self.Frame_10,width=12,state='readonly')
        self.Combobox_21.bind("<<ComboboxSelected>>",lambda event:self.Combobox_21_ComboboxSelected(event))
        self.Combobox_21.pack(side='left',padx=2,pady=(2,0),ipadx=1,ipady=1)
        self.LabelFrame_23=tk.LabelFrame(root,text='提问',width=8,height=1,background='#e0e0e0')
        self.LabelFrame_23.grid(row=1,column=2,sticky='nesw',padx=(0,5))
        self.LabelFrame_24=tk.LabelFrame(root,text='其他',width=8,height=1,background='#e0e0e0')
        self.LabelFrame_24.grid(row=1,column=3,sticky='nesw')
        self.Frame_25=tk.Frame(root,width=8,height=1)
        self.Frame_25.grid(row=0,column=0,rowspan=2,sticky='nesw',padx=(5,0),ipady=10)
        self.Scrollbar_7=tk.Scrollbar(self.Frame_25,orient='vertical')
        self.Scrollbar_7.pack(side='right',fill='y')
        self.Scrollbar_6=tk.Scrollbar(self.Frame_25,orient='horizontal')
        self.Scrollbar_6.pack(side='bottom',fill='x')
        self.Treeview_5=ttk.Treeview(self.Frame_25,show='headings',selectmode='browse')
        self.Treeview_5.pack(side='left',fill='both',expand=1)
        self.Frame_32=tk.Frame(self.LabelFrame_22)
        self.Frame_32.pack(padx=2,pady=2)
        self.Label_31=tk.Label(self.Frame_32,text='进度')
        self.Label_31.pack(padx=2)
        self.Progressbar_33=ttk.Progressbar(self.Frame_32)
        self.Progressbar_33.pack(padx=2)
        self.icoButton_28=tk.PhotoImage(file=f'{cmm.bPath}ico/start.png')
        self.Button_28=tk.Button(self.LabelFrame_22,text='开始',command=lambda:self.Button_28_Click(),height=50,width=98,image=self.icoButton_28,compound='left')
        self.Button_28.image=self.icoButton_28
        self.Button_28.pack(padx=2,pady=(2,8))
        self.icoButton_29=tk.PhotoImage(file=f'{cmm.bPath}ico/imp.png')
        self.Button_29=tk.Button(self.LabelFrame_22,text='导入',command=lambda:self.Button_29_Click(),width=98,height=30,state='disabled',image=self.icoButton_29,compound='left')
        self.Button_29.image=self.icoButton_29
        self.Button_29.pack(padx=2,pady=2)
        self.Frame_62=tk.Frame(self.LabelFrame_23,background='#dfefff')
        self.Frame_62.pack()
        self.icoButton_30=tk.PhotoImage(file=f'{cmm.bPath}ico/random.png')
        self.Button_30=tk.Button(self.LabelFrame_23,text='随机',command=lambda:self.Button_30_Click(),width=98,height=30,image=self.icoButton_30,compound='left')
        self.Button_30.image=self.icoButton_30
        self.Button_30.pack(padx=2,pady=(5,5))
        self.icoButton_42=tk.PhotoImage(file=f'{cmm.bPath}ico/order.png')
        self.Button_42=tk.Button(self.LabelFrame_23,text='顺序',command=lambda:self.Button_42_Click(),width=98,height=30,image=self.icoButton_42,compound='left')
        self.Button_42.image=self.icoButton_42
        self.Button_42.pack(padx=2,pady=(5,5))
        self.icoButton_17=tk.PhotoImage(file=f'{cmm.bPath}ico/std.png')
        self.Button_17=tk.Button(self.LabelFrame_24,text='学生',command=lambda:self.Button_17_Click(),height=30,width=98,compound='left',image=self.icoButton_17)
        self.Button_17.image=self.icoButton_17
        self.Button_17.pack(padx=2,pady=2)
        self.icoButton_34=tk.PhotoImage(file=f'{cmm.bPath}ico/course.png')
        self.Button_34=tk.Button(self.LabelFrame_24,text='课程',command=lambda:self.Button_34_Click(),width=98,compound='left',height=30,image=self.icoButton_34)
        self.Button_34.image=self.icoButton_34
        self.Button_34.pack(padx=2,pady=2)
        self.icoButton_19=tk.PhotoImage(file=f'{cmm.bPath}ico/setup.png')
        self.Button_19=tk.Button(self.LabelFrame_24,text='设置',command=lambda:self.Button_19_Click(),width=98,image=self.icoButton_19,compound='left',height=30)
        self.Button_19.image=self.icoButton_19
        self.Button_19.pack(padx=2,pady=2)
        self.icoButton_35=tk.PhotoImage(file=f'{cmm.bPath}ico/analysis.png')
        self.Button_35=tk.Button(self.LabelFrame_22,text='统计',command=lambda:self.Button_35_Click(),height=30,width=98,image=self.icoButton_35,compound='left')
        self.Button_35.image=self.icoButton_35
        self.Button_35.pack(padx=2,pady=2)
        self.icoRadiobutton_38=tk.PhotoImage(file=f'{cmm.bPath}ico/mute.png')
        self.Radiobutton_38=tk.Radiobutton(self.Frame_62,command=lambda:self.Radiobutton_38_Click(),image=self.icoRadiobutton_38,background='#dfefff')
        self.Radiobutton_38.image=self.icoRadiobutton_38
        self.Radiobutton_38.pack(anchor='n',side='right',padx=(0,10),pady=(8,0))
        self.Combobox_49Ft=tk.font.Font(**{'family': '微软雅黑', 'size': 8, 'weight': 'normal', 'slant': 'roman'})
        self.Combobox_49=ttk.Combobox(self.Frame_62,font=self.Combobox_49Ft,width=10,height=5)
        self.Combobox_49.pack(anchor='w',side='bottom',padx=5,pady=2)
        self.icoRadiobutton_37=tk.PhotoImage(file=f'{cmm.bPath}ico/music.png')
        self.Radiobutton_37=tk.Radiobutton(self.Frame_62,command=lambda:self.Radiobutton_37_Click(),image=self.icoRadiobutton_37,background='#dfefff')
        self.Radiobutton_37.image=self.icoRadiobutton_37
        self.Radiobutton_37.pack(anchor='n',side='left',padx=(10,0),pady=(8,0))
        self.Frame_63=tk.Frame(self.LabelFrame_23,background='#dfefff')
        self.Frame_63.pack(pady=5,ipady=2)
        self.Radiobutton_40=tk.Radiobutton(self.Frame_63,command=lambda:self.Radiobutton_40_Click(),anchor='w',background='#dfefff')
        self.Radiobutton_40.grid(row=0,column=0,sticky='s')
        self.Radiobutton_41=tk.Radiobutton(self.Frame_63,command=lambda:self.Radiobutton_41_Click(),background='#dfefff')
        self.Radiobutton_41.grid(row=0,column=1,sticky='s')
        self.Radiobutton_43=tk.Radiobutton(self.Frame_63,command=lambda:self.Radiobutton_43_Click(),background='#dfefff')
        self.Radiobutton_43.grid(row=0,column=2,sticky='s')
        self.Radiobutton_44=tk.Radiobutton(self.Frame_63,command=lambda:self.Radiobutton_44_Click(),background='#dfefff')
        self.Radiobutton_44.grid(row=0,column=3,sticky='s')
        self.Radiobutton_46=tk.Radiobutton(self.Frame_63,command=lambda:self.Radiobutton_46_Click(),background='#dfefff')
        self.Radiobutton_46.grid(row=0,column=4,sticky='s')
        self.icoButton_48=tk.PhotoImage(file=f'{cmm.bPath}ico/analysis.png')
        self.Button_48=tk.Button(self.LabelFrame_23,text='统计',command=lambda:self.Button_48_Click(),width=98,height=30,image=self.icoButton_48,compound='left')
        self.Button_48.image=self.icoButton_48
        self.Button_48.pack(padx=2,pady=2)
        self.Label_50=tk.Label(self.Frame_63,text='A',background='#dfefff')
        self.Label_50.grid(row=1,column=0,sticky='w',padx=2)
        self.Label_51=tk.Label(self.Frame_63,text='B',background='#dfefff')
        self.Label_51.grid(row=1,column=1,sticky='w',padx=3)
        self.Label_52=tk.Label(self.Frame_63,text='C',background='#dfefff')
        self.Label_52.grid(row=1,column=2,sticky='w',padx=4)
        self.Label_53=tk.Label(self.Frame_63,text='D',background='#dfefff')
        self.Label_53.grid(row=1,column=3,sticky='w',padx=4)
        self.Label_54=tk.Label(self.Frame_63,text='E',background='#dfefff')
        self.Label_54.grid(row=1,column=4,sticky='w',padx=4)
        self.icoButton_55=tk.PhotoImage(file=f'{cmm.bPath}ico/ok.png')
        self.Button_55=tk.Button(self.Frame_63,text='确定',command=lambda:self.Button_55_Click(),state='disabled',compound='left',image=self.icoButton_55)
        self.Button_55.image=self.icoButton_55
        self.Button_55.grid(row=2,column=0,columnspan=5,padx=2,pady=2,ipadx=10)
        self.Frame_56=tk.Frame(self.LabelFrame_24)
        self.Frame_56.pack(padx=2,pady=2)
        self.Listbox_57Ft=tk.font.Font(**{'family': '微软雅黑', 'size': 10, 'weight': 'normal', 'slant': 'roman'})
        self.Listbox_57=tk.Listbox(self.Frame_56,font=self.Listbox_57Ft,height=5,width=15,background='gainsboro')
        self.Listbox_57.pack(side='left',fill='y')
        self.Scrollbar_58=tk.Scrollbar(self.Frame_56)
        self.Scrollbar_58.pack(anchor='w',side='right',fill='y',expand=1)
        self.icoButton_59=tk.PhotoImage(file=f'{cmm.bPath}ico/play.png')
        self.Button_59=tk.Button(self.LabelFrame_24,text='播放',command=lambda:self.Button_59_Click(),width=98,compound='left',height=30,image=self.icoButton_59)
        self.Button_59.image=self.icoButton_59
        self.Button_59.pack(padx=2,pady=2)
        self.Label_61Ft=tk.font.Font(**{'family': '微软雅黑', 'size': 9, 'weight': 'normal', 'slant': 'roman'})
        self.Label_61=tk.Label(root,text='考勤情况',font=self.Label_61Ft)
        self.Label_61.grid(row=2,column=0,rowspan=4,sticky='w',padx=5)
        self.icoButton_64=tk.PhotoImage(file=f'{cmm.bPath}ico/calendar.png')
        self.Button_64=tk.Button(self.LabelFrame_22,text='查询',command=lambda:self.Button_64_Click(),height=30,width=98,image=self.icoButton_64,compound='left')
        self.Button_64.image=self.icoButton_64
        self.Button_64.pack(padx=2,pady=2)
    def Combobox_12_ComboboxSelected(self,event):  #选择了一个学期    
        self.Combobox_14['values']=taDB.getClass(self.Combobox_12.get())  #获得该学期全部班级名称
        self.Combobox_14.set("") #设置输入框为空
        if cmm.thisWeek()>22 or cmm.thisWeek()<1:  messagebox.showinfo('提示','请先设置好第1周日期')
    def Combobox_14_ComboboxSelected(self,event):  #选择了一个班级
        lst=taDB.classCourse(self.Combobox_14.get())
        self.Combobox_21['values']=lst
        if len(lst)==1:  #只有一个课程
            self.Combobox_21.current(0)
            self.Combobox_21_ComboboxSelected(0)
        #Fun.GetElement('mdfStudentUI','Label_16')['text']='班级人数:' str(aa)
    def Combobox_21_ComboboxSelected(self,event):#选择了一个课程
        root.title(f'课堂助手 {dateNow} 第{cmm.thisWeek()}周')
        taDB.qrClass(self.Combobox_14.get(),self.Combobox_21.get())                
        showTB()  
    def tips(self):  #提示     
        if not self.Combobox_12.get() or not self.Combobox_14.get() or not self.Combobox_12.get():
            messagebox.showinfo('提示','请先选择好学期、班级和课程')
            return 1
        else: return 0
    def Button_28_Click(self):  #点击开始考勤 
        #taDB.delD()   #删除测试时的临时数据
        if self.tips():return 0
        global begin      
        self.Progressbar_33['maximum']=len(taDB.lstAll)  # 设置进度条的最大值         
        dfr=datetime.now()-datetime.strptime(cmm.timeWr,'%Y-%m-%d %H:%M:%S')#与上次考勤间隔时间
        if dfr.total_seconds()>=0: dfr=dfr.total_seconds()/60  #转化成分钟
        else: 
            messagebox.showinfo('提示','日期不对,请核对日期')
            return 0
        if dfr>45 and not begin:  #上次考勤离现在超过45分钟,开始新考勤
            begin=1
            self.Button_28['text']='暂停'
            threading.Thread(target=createT,args=(0,),daemon=1).start()# 设置为守护线程
        elif begin==1: #正在考勤中
            if running.is_set(): #当前处于运行状态,要设置为暂停
                running.clear()  #阻塞wait()
                self.Button_28['bg']='lightpink'  #按键暂停背景色
            else:  #当前处于暂停状态,要设置为运行
                running.set()  #放行wait()
                self.Button_28['bg']='SystemButtonFace'   #按键正常背景色 
        elif dfr<45:  #重新考勤     
            if messagebox.askyesno('提示','已经考勤过,要重新考勤吗?'):
                for iid in self.Treeview_5.get_children():  #清空视图中考勤内容
                    self.Treeview_5.set(iid,'考勤','')
                self.Button_28['text']='暂停'
                begin=1
                threading.Thread(target=createT,args=(1,),daemon=1).start()# 设置为守护线程 
    def Button_35_Click(self):  #点击了考勤统计
        if self.tips():return 0
        topWnd(sttUI,'sttUI')
    def Button_64_Click(self,):#查询
        if self.tips():return 0
        selDate=cmm.sltDate()  
        lst=taDB.sttAll(1,0,0,0,selDate) 
        root.title(f'{root.title()}---指定日期 {selDate}')
        tpl=('迟到','早退','请假','旷课','出勤')        
        for it in lst:
            flag=0
            for i in range(3,len(it)):
                if it[i]:
                    for iid in self.Treeview_5.get_children():
                        if self.Treeview_5.set(iid,'学号')==it[0]:
                            self.Treeview_5.set(iid,'考勤',tpl[i-3])#写入视图中
                            flag=11
                            break
                if flag==11:break
            else:
                for iid in self.Treeview_5.get_children():
                    if self.Treeview_5.set(iid,'学号')==it[0]:
                        self.Treeview_5.set(iid,'考勤','到')#写入视图中            
    def Radiobutton_37_Click(self):  #点击了前奏音乐
        self.Combobox_49['state']='normal'
    def Radiobutton_38_Click(self):  #点击了前奏静音
        self.Combobox_49['state']='disabled'            
    def Button_30_Click(self):  #随机点名
        if self.tips():return 0 
        self.intVar2.set(0)  #不评分        
        if not self.lstTV:
            for iid in self.Treeview_5.get_children():
                if self.Treeview_5.set(iid,'考勤') not in ('请假','旷课','出勤'):
                    self.lstTV.append(iid)  #写入随机列表
        idx=random.randint(0, len(self.lstTV)-1)          
        self.ctr(idx)  #点名         
    def Button_42_Click(self):  #顺序点名
        self.intVar2.set(0)  #不评分
        if not self.lstTV:
            for iid in self.Treeview_5.get_children():
                if self.Treeview_5.set(iid,'考勤') not in ('请假','旷课','出勤'):
                    self.lstTV.append(iid)  #写入随机列表        
        self.ctr(0)   #点名  
    def effectG(self,idx):  #随机点名效果及点名
        if not cmm.running:
            iid=self.lstTV[idx]  #选中的iid 
            self.Treeview_5.selection_set(iid)
            self.Treeview_5.see(iid)
            self.Treeview_5.focus(iid)
            threading.Thread(target=ttsSay,args=(f"有请{self.Treeview_5.set(iid,'姓名')}",110),daemon=1).start()#创建线程读名字
            self.Button_55['state']='normal'
            self.stdNum=self.Treeview_5.set(iid,'学号')
            del self.lstTV[idx] 
            sc=self.Treeview_5.set(iid,'提问次数')
            if sc: sc =1 
            else: sc=1 
            self.Treeview_5.set(iid,'提问次数',sc)  #在视图中写入提问次数
            return 0
        id=random.randint(0, len(self.lstTV)-1)
        self.Treeview_5.selection_set(self.lstTV[id])
        self.Treeview_5.see(self.lstTV[id]) 
        root.after(100,self.effectG,idx)  #100ms后再次运行
    def ctr(self,idx):  #随机或者顺序提问学生   
        cmm.running=1      
        if self.intVar.get()==1: #播放音乐
            threading.Thread(target=playsound,args=(f'{cmm.bPath}music/{self.Combobox_49.get()}',),daemon=1).start()# 设置为守护线程
        self.effectG(idx) #随机点名效果及点名
    def Button_55_Click(self):  #提问成绩写入数据库。确定
        tpl=('A','B','C','D','E')
        asw=tpl[self.intVar2.get()-1]       
        if not taDB.wrAttd(1,self.stdNum,asw):
            messagebox.showinfo('提示','日期不对或者今天没有考勤,请核对')
            return 0
        for iid in self.Treeview_5.get_children(): #显示在视图中
            if self.Treeview_5.set(iid,'学号')==self.stdNum:
                asw=self.Treeview_5.set(iid,'回答成绩') asw
                self.Treeview_5.set(iid,'回答成绩',asw) 
        self.intVar2.set(0)
        self.Button_55['state']='disabled'       
    def Button_48_Click(self):  #点击了提问统计
        if self.tips():return 0
        topWnd(sttUI,'sttUI',1)
    def Button_29_Click(self):
        pass
    def Button_19_Click(self):  #点击了设置
        topWnd(attdSetup,'attdSetupUI')
    def Button_17_Click(self):  #点击了学生
        topWnd(mdfStudentUI,'mdfStudentUI')
    def Button_34_Click(self):  #点击了课程
        topWnd(mdfCourseUI,'mdfCourseUI')
    def exit(self):
        with open(f'{cmm.bPath}default.ini','w',encoding="utf-8-sig") as f:  # 保存配置文件
            cmm.cfgParser['default']['firstWeek']=cmm.firstWeek
            cmm.cfgParser['default']['restT']=str(cmm.restT)
            cmm.cfgParser['default']['timeWr']=cmm.timeWr
            cmm.cfgParser.write(f)             
        root.destroy()     
    def Radiobutton_40_Click(self,):
        pass
    def Radiobutton_41_Click(self,):
        pass    
    def Radiobutton_43_Click(self):
        pass
    def Radiobutton_44_Click(self,):
        pass
    def Radiobutton_46_Click(self,):
        pass         
    def Button_59_Click(self):
        global engine
        slt=self.Listbox_57.curselection()
        if not slt: slt=0
        threading.Thread(target=ttsSay,args=(self.Listbox_57.get(slt),180),daemon=1).start()# 设置为守护线程  
#-----------------------------------------------------Do not delete this line--------------            
ttsLock=threading.Lock()
begin=0  #线程没有启动,语音引擎
running=threading.Event()  # False=暂停,True=运行
running.set()   # 初始不暂停
caller=0  #随机点名生成器
def showTB():  #显示学生名单视图    
    for i in myDlg.Treeview_5.get_children(): myDlg.Treeview_5.delete(i) #清空表        
    lstTmp=['','','','','','']
    for i,it in enumerate(taDB.lstAll):    #更新列表
        lstTmp[0]=i 1  #序号
        lstTmp[1]=it[1]
        lstTmp[2]=it[2]
        if i%2==1: myDlg.Treeview_5.insert('','end',value=lstTmp)   #插入奇数行数据
        else: myDlg.Treeview_5.insert('','end',value=lstTmp,tags='evenColor')   #插入偶数行数据
    #myDlg.Treeview_5.insert('','end',value='')  #插入一空行,看清所有内容
def loading(byte):
    myDlg.Progressbar_33['value']=byte  # 设置指针位置
    aa=round(byte/len(taDB.lstAll)*100)
    if aa>=100: myDlg.Label_31['text']='100%'
    else:  myDlg.Label_31['text']=str(round(byte/len(taDB.lstAll)*100)) '%'
def ttsSay(text,sayRate=110):  #语音合成及朗读
    with ttsLock:
        engine = pyttsx3.init()  #创建语音合成对象
        engine.setProperty('rate', sayRate)  #语速10字/分钟,默认值200    
        engine.say(text)  #不会实际执行,而是进行相关设置
        engine.runAndWait()  #开启运行以及阻塞,等待任务完成才继续向后执行def ttsSay(text,speed):  #语音合成及朗读
def createT(reW):  #读学生名字
    global begin
    threading.Thread(target=ttsSay,args=('现在开始考勤',150),daemon=1).start()#开始提醒 
    time.sleep(3)
    for i,it in enumerate(taDB.lstAll): 
        running.wait()  #暂停       
        loading(i 1)
        iid=myDlg.Treeview_5.get_children()[i]
        myDlg.Treeview_5.selection_set(iid)   #选中它
        myDlg.Treeview_5.see(iid)   #滚动到位置        
        threading.Thread(target=ttsSay,args=(it[2],),daemon=1).start()# 设置为守护线程
        time.sleep(cmm.restT)        
        myDlg.Treeview_5.set(iid,'考勤','到')#写入视图中  
    myDlg.Button_28['text']='开始'  #考勤结束设置
    myDlg.Label_31['text']='进度'  #考勤结束设置
    begin=2  #考勤结束设置
    myDlg.Progressbar_33['value']=0  
    with ttsLock:  
        cmm.timeWr=taDB.wrAttd(reW)  #将考勤信息写入数据库 
    baseStt()
def baseStt(): #考勤完毕在状态栏显示本次考勤情况
    lst=[0,0,0,0,0]
    tpl=("请假","迟到","早退","旷课","出勤")
    for iid in myDlg.Treeview_5.get_children():  #粗略统计本次考勤情况
        att=myDlg.Treeview_5.set(iid,'考勤')
        if att!='到':
            for i,it in enumerate(tpl):
                if it==att: lst[i] =1
    s=''
    for i,it in enumerate(lst):
        if it>0:s=f'{s}{tpl[i]}{it}人,'
    if s: myDlg.Label_61['text']='考勤情况:' s.rstrip(',')   
    else: myDlg.Label_61['text']='考勤情况:全部到齐'
def clrStd(iid,it):  #修改考勤结果,并根据情况写入数据库
    for at in ("到","请假","迟到","早退","旷课","出勤"):
        if it==at:  
            myDlg.Treeview_5.set(iid,'考勤',at)#写入视图中
            break
    if begin==1: return 0 #正在考勤中,暂时不保存 
    taDB.wrAttd(1,iid)  #修改某个学生当前考勤信息
    baseStt()
def rightMenu(event):  #右击视图弹出的菜单
    iid = myDlg.Treeview_5.identify('item', event.x, event.y)
    col = myDlg.Treeview_5.identify_column(event.x)  # 获取列ID(例如 #1)
    colIdx = int(col.replace("#", "")) - 1
    cellV =myDlg.Treeview_5.set(iid, colIdx)  # 获取指定单元格的值
    if not cellV: return 0
    myDlg.Treeview_5.selection_set(iid)
    menu = tk.Menu(root, tearoff=0)  #创建父菜单
    for it in ("到","请假","迟到","早退","旷课","出勤"):
        menu.add_cascade(label=it,command=lambda at=it:clrStd(iid,at))  #父菜单项
    menu.post(event.x_root, event.y_root)  #显示弹出菜单  
def topWnd(wnd,sname,sttScore=0):  #创建模态窗口。sttScore统计提问得分
    top =tk.Toplevel()        #创建一个顶级窗口
    top.transient(root)  #去掉最小化按钮
    top.resizable(0,0) #窗口不可变
    top.title(f'第1-{cmm.thisWeek()}周考勤')
    if sname=='sttUI':  #统计窗口        
        xp=cmm.root.winfo_x()  #父窗口x坐标
        yp=cmm.root.winfo_y()  #父窗口y坐标
        hp=cmm.root.winfo_height()  #父窗口高度
        wp=cmm.root.winfo_width()  #父窗口宽度
        top.geometry(f'750x380 {int((wp-720)/2) xp} 0') #宽x高 x坐标 y坐标
    top.grab_set()  # 设置窗口为模态(阻止用户操作主窗口)
    if sttScore: dlg=getattr(wnd,sname)(top,sttScore)  #统计提问得分
    else: dlg=getattr(wnd,sname)(top)  
    if sname=='sttUI':  #统计窗口
        if sttScore: dlg.showStt(taDB.sttAll(0,0,0,1),11) #统计提问得分。11表示首次打开窗口
        else: dlg.showStt(taDB.sttAll(0),11) #统计全班一个学期考勤情况。11表示首次打开窗口                    
    top.wait_window()  #停止主窗口事件循环。等待模态窗口关闭   
def callR(order=0):  #随机点名。order=1顺序点名
    lstRdm=[]
    for it in taDB.lstAll: lstRdm.append((it[1],it[2])) #添加学生
    idx=0
    while lstRdm:
        if not order:idx=random.randint(0,len(lstRdm)-1)
        yield lstRdm.pop(idx)
if __name__ == "__main__":  #以下内容,请勿随意改动-----
    root = tk.Tk()
    root.option_add("*Font", "微软雅黑 11")  #全局字体,控制基于root的控件的字体大小
    root.option_add("*Menu.font", "微软雅黑 10")  #各菜单项字体    
    lclTime=time.localtime(time.time())
    dateNow=time.strftime('%Y-%m-%d',lclTime) 
    cmm.dateNow=dateNow    
    winW=915
    winH=425
    root.rowconfigure(1,weight=1)
    screenW = root.winfo_screenwidth()
    screenH = root.winfo_screenheight()
    mainWin ='%dx%d %d %d'%(winW,winH,(screenW-winW)//2,(screenH-winH)//2)
    root.geometry(mainWin)
    root.resizable(False, False)
    root.iconbitmap(f'{cmm.bPath}ico/cra.ico')
    cmm.root=root
    myDlg=mainUI(root) 
    cmm.myDlg=myDlg     
    root.mainloop()