嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):78630559
本次赞助数额为: 2 元微信扫码支付:2 元
请留下您的邮箱,我们将在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()