xhtdtk 发表于 2023-3-21 15:57

机器人老师做一个记录孩子上课表现的程序

本帖最后由 xhtdtk 于 2023-3-21 15:57 编辑

一、初衷

我在机器人教师岗位差不多有一年半了,周上课次数也从刚开始的一周一节,到现在的一周八节,这还不算有体验课和补课的情况下,每节课上足90分钟。
喉咙不仅靠凉茶续命,也没有充足的时间给每个学生做课评,因为下班还有自己的家庭和兴趣爱好。
于是在我脑子里盘旋了一个想法,写一个帮助我弄课评的程序,当然我没有急于动手,而是在坐车、蹲坑、吃饭、睡觉前不断完善我的想法。

从最初的想法到成品,想法大概是这样:
1、做一个简单的界面,从上课的“引入主题-分析结构-搭建-编程-展示”五个步骤出发,描述对应步骤学生上课表现的细节,最后生成一段课评。
(这个和我平时手写课评没什么区别,只是有了个模板照着写而已,并不是我想要的,我要更简单一点)
2、以八上课前后的八个完整步骤出发,每个步骤设置对应的题目和选项,且以stem八项能力为基础从每道题展现出来,保存在数据库形成一窜记录。
(这个启发是在测星座、测情商的时候,只需要完成一些简单的问答就能直接进行总结,这就是我想要的,而且有了记录我还能做年度总结,这是受网易云音乐的启发)

二、主界面



需要实现的功能:
1、根据选择的“任课教师”获取对应教师上课的“时间段”
2、根据选择的“时间段”在“列表框”显示对应班级的学生
3、根据选择的"时间段"在"上课日期"自动查找最近的上课日期,并且刷新显示周几
4、根据选择的“上课课程”阶段显示对应的课程
5、双击“列表框”弹出分界面开始做问答记录,并且先检测所有的信息是否选择完整(如下图1),且当天日期如果与上课日期超过7天则弹窗提示是否继续做问答记录(如下图2)
6、刷新学生的问答记录


图1


图2

# 主界面没有用class
import sql # 自己写的库
import time,datetime
import tk_top # 自己写的分界面
import openpyxl
import re
import json

import tkinter
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from tkinter import scrolledtext
from tkinter import *

# 界面抬头
main=tkinter.Tk()
main.title('零橙教育孩子成长记录问卷表')
main.geometry('520x310+300+210')

# 任课教师
x_courseTeacher=10
y_courseTeacher=10
label_courseTeacher=Label(main,text='任课教师:')
label_courseTeacher.place(x=x_courseTeacher,y=y_courseTeacher)
cmb_courseTeacher=ttk.Combobox(main,height=10,width=15)
cmb_courseTeacher.place(x=x_courseTeacher+65,y=y_courseTeacher)
cmb_courseTeacher.set('--请选择--')
tuple_teacherMessage=sql.getTeacherMessage() # 从数据库获取教师名字 (('序号','教师','所有时间段'))
lst_teacherName=[]
for eachTeacher in tuple_teacherMessage:
      lst_teacherName.append(eachTeacher)
cmb_courseTeacher['value']=lst_teacherName # sql

# 上课课程
x_courseName=220
y_courseName=10
label_courseName=Label(main,text='上课课程:')
label_courseName.place(x=x_courseName,y=y_courseName)
cmb_courseLevel=ttk.Combobox(main,height=10,width=10)
cmb_courseLevel.place(x=x_courseName+65,y=y_courseName)
cmb_courseLevel.set('--请选择--')
cmb_courseLevel['value']=('启蒙初阶','启蒙进阶','启蒙高阶','机器人一阶','机器人二阶','机器人三阶','机器人四阶','机器人五阶','机器人六阶')
cmb_courseName=ttk.Combobox(main,height=10,width=16)
cmb_courseName.place(x=x_courseName+160,y=y_courseName)
cmb_courseName.set('--请选择--')
def showCourseName(event):
      cmb_courseName.set('--请选择--')
      courseLevel=cmb_courseLevel.get() # 从界面获取课程阶段
      tuple_courseMessage=sql.getCourseMessage_courseLevel(courseLevel) # 从数据库获取教师名字 (('序号','教师','所有时间段','结构','知识点'))
      lst_courseName=[]
      for eachCourse in tuple_courseMessage:
                lst_courseName.append(eachCourse)
      cmb_courseName['value']=lst_courseName # sql
'''根据课程阶段筛选课程'''
cmb_courseLevel.bind('<<ComboboxSelected>>',showCourseName)

# 是否代课
def showProxyTeacher():
      global label_proxyTeacher,cmb_proxyTeacher
      x_proxyTeacher=220
      y_proxyTeacher=40
      label_proxyTeacher=Label(main,text='代课老师:')
      label_proxyTeacher.place(x=x_proxyTeacher,y=y_proxyTeacher)
      cmb_proxyTeacher=ttk.Combobox(main,height=10,width=15)
      cmb_proxyTeacher.place(x=x_proxyTeacher+65,y=y_proxyTeacher)
      cmb_proxyTeacher.set('--请选择--')
      tuple_teacherMessage=sql.getTeacherMessage() # 从数据库获取教师名字 (('序号','教师','所有时间段'))
      lst_teacherName=[]
      for eachTeacher in tuple_teacherMessage:
                lst_teacherName.append(eachTeacher)
      cmb_proxyTeacher['value']=lst_teacherName # sql
'''选择是,显示代课老师选择项'''
def destroyProxyTeacher():
      try:
                label_proxyTeacher.destroy()
                cmb_proxyTeacher.destroy()
      except NameError:
                pass
      except Exception as e:
                print(e)
'''选择否,删除代课老师选择项'''
x_TFproxyTeacher=10
y_TFproxyTeacher=40
label_TFproxyTeacher=Label(main,text='是否代课:')
label_TFproxyTeacher.place(x=x_TFproxyTeacher,y=y_TFproxyTeacher)
radioButton_TFproxyTeacher=IntVar()
radioButton_TFproxyTeacher.set(2)
TFproxyTeacher1=Radiobutton(main,text="是",variable=radioButton_TFproxyTeacher,value=1,command=lambda:showProxyTeacher())
TFproxyTeacher1.place(x=x_TFproxyTeacher+60,y=y_TFproxyTeacher-2)
TFproxyTeacher2=Radiobutton(main,text="否",variable=radioButton_TFproxyTeacher,value=2,command=lambda:destroyProxyTeacher())
TFproxyTeacher2.place(x=x_TFproxyTeacher+115,y=y_TFproxyTeacher-2)

# 时间段
x_courseTime=10
y_courseTime=70
label_courseTime=Label(main,text='时间段 :')
label_courseTime.place(x=x_courseTime,y=y_courseTime)
cmb_courseTime=ttk.Combobox(main,height=10,width=15)
cmb_courseTime.place(x=x_courseTime+65,y=y_courseTime)
cmb_courseTime.set('--请选择--')
def showCourseTime(event):
      cmb_courseTime.set('--请选择--') # 更换任课老师后还原成初始值
      for eachStudent in table_studentFinshed.get_children(): # 删除界面表格信息
                table_studentFinshed.delete(eachStudent)
      courseTeacher=cmb_courseTeacher.get() # 从界面获取任课教师姓名
      tuple_teacherMessage=sql.getTeacherMessage() # 从数据库获取教师名字 (('序号','教师','所有时间段'))
      for eachTeacher in tuple_teacherMessage:
                if eachTeacher == courseTeacher:
                        courseTime=eachTeacher
                        cmb_courseTime['value']=courseTime.split('\n') # sql
                        break
'''根据选择任课教师而筛选时间段'''
cmb_courseTeacher.bind('<<ComboboxSelected>>',showCourseTime)

# 上课日期
x_courseDate=220
y_courseDate=70
label_courseDate=Label(main,text='上课日期:')
label_courseDate.place(x=x_courseDate,y=y_courseDate)
entry_courseDate_year=Entry(main,width=5)
entry_courseDate_year.place(x=x_courseDate+65,y=y_courseDate)
label_courseDate_year=Label(main,text='年')
label_courseDate_year.place(x=x_courseDate+100,y=y_courseDate)
entry_courseDate_month=Entry(main,width=6)
entry_courseDate_month.place(x=x_courseDate+120,y=y_courseDate)
label_courseDate_month=Label(main,text='月')
label_courseDate_month.place(x=x_courseDate+155,y=y_courseDate)
entry_courseDate_day=Entry(main,width=6)
entry_courseDate_day.place(x=x_courseDate+175,y=y_courseDate)
label_courseDate_day=Label(main,text='日')
label_courseDate_day.place(x=x_courseDate+210,y=y_courseDate)
lst_week=['周一','周二','周三','周四','周五','周六','周日']
def update_weekFromCourseDate():
      year=entry_courseDate_year.get()
      month=entry_courseDate_month.get()
      day=entry_courseDate_day.get()
      if not '' in :
                try:
                        year,month,day=int(year),int(month),int(day)
                        courseWeek=lst_week
                        label_courseDate_date=Label(main,text=courseWeek,fg='blue')
                        label_courseDate_date.place(x=x_courseDate+240,y=y_courseDate)
                except:
                        pass
      main.after(1000,update_weekFromCourseDate)
'''根据填写的日期显示星期'''
update_weekFromCourseDate()

# 学生课评完成情况表
x_studentFinshed=10
y_studentFinshed=100
table_studentFinshed_column=['序号','学生','考勤','课程','上次保存记录']
table_studentFinshed=ttk.Treeview(
      master=main,
      columns=table_studentFinshed_column,
      height=7,
      show='headings',
      style='Treeview'
)
table_studentFinshed.column('序号',width=30)
table_studentFinshed.column('学生',width=90)
table_studentFinshed.column('考勤',width=90)
table_studentFinshed.column('课程',width=140)
table_studentFinshed.column('上次保存记录',width=150)
for i in range(len(table_studentFinshed_column)):
      table_studentFinshed.column(table_studentFinshed_column,anchor='c')
      table_studentFinshed.heading(table_studentFinshed_column,text=table_studentFinshed_column)
table_studentFinshed.place(x=x_studentFinshed,y=y_studentFinshed)
def showStudent(event):
      for eachStudent in table_studentFinshed.get_children(): # 删除界面表格信息
                table_studentFinshed.delete(eachStudent)

      courseTeacher=cmb_courseTeacher.get() # 从界面获取任课教师姓名
      courseTime=cmb_courseTime.get() # 从界面获取时间段
      tuple_studentMessage=sql.getStudentMessage(courseTeacher,courseTime) # 从数据库获取学生信息 (('序号','学生姓名','时间段','任课教师'))
      lst_studentName=[]
      i=1
      for eachStudenMessage in tuple_studentMessage:
                lst_studentName.append(])
                i=i+1
      lst_studentName.append(['last','双击更新'])
      for eachStudentName in lst_studentName:
                table_studentFinshed_values=eachStudentName+['','',''] # sql
                table_studentFinshed.insert('','end',value=table_studentFinshed_values)

      courseTime=cmb_courseTime.get()
      entry_courseDate_year.delete(0,END)
      entry_courseDate_month.delete(0,END)
      entry_courseDate_day.delete(0,END)
      for i in range(-1,6):
                if lst_week[(datetime.datetime.now() - datetime.timedelta(days=i)).date().weekday()] in courseTime:
                        weekDate=datetime.datetime.now() - datetime.timedelta(days=i)
                        entry_courseDate_year.insert(0,weekDate.year)
                        entry_courseDate_month.insert(0,weekDate.month)
                        entry_courseDate_day.insert(0,weekDate.day)
                        break
'''
清除界面表格信息,添加新信息;
根据时间段自动填写日期
'''
cmb_courseTime.bind('<<ComboboxSelected>>',showStudent)
def showTest(event):
      # 获取界面表格选择的学生信息
      tableValue=table_studentFinshed.item(table_studentFinshed.selection(),option='values')
      if tableValue == ('last', '双击更新', '', '', ''):
                for eachStudent in table_studentFinshed.get_children():
                        eachTableValue=table_studentFinshed.item(eachStudent)['values']
                        studentName=eachTableValue
                        appriseLog=sql.getAppriseLog_studentName(studentName)
                        if appriseLog != ():
                              appriseLog_datetime=appriseLog[-1]
                              appriseLog_courseName=appriseLog[-1]
                              appriseLog_attendanceStatus=appriseLog[-1]
                              eachTableValue=appriseLog_attendanceStatus
                              eachTableValue=appriseLog_courseName
                              eachTableValue=appriseLog_datetime
                              table_studentFinshed.item(eachStudent,values=eachTableValue)
                return '更新完毕'
      else:
                try:
                        studentName=tableValue
                except IndexError:
                        return False

      # 获取界面基本信息
      courseTeacher=cmb_courseTeacher.get() # 获取任课老师
      courseName=cmb_courseName.get() # 获取课程
      if courseName in ['--请选择--']:
                messagebox.showinfo('未选择提示','请选择上课课程')
                return '未选择课程'
      try:
                proxyTeacher=cmb_proxyTeacher.get() # 获取代课老师
      except:
                proxyTeacher='无'
      courseTime=cmb_courseTime.get() # 获取时间段
      year=entry_courseDate_year.get() # 获取日期,年
      month=entry_courseDate_month.get() # 获取日期,月
      day=entry_courseDate_day.get() # 获取日期,日
      if '' in :# 判断是否填写
                messagebox.showinfo('未填写提示','请填写上课日期')
                return '未填写日期'
      year,month,day=int(year),int(month),int(day)
      courseWeek=lst_week
      if not courseWeek in courseTime:
                yesno=messagebox.askyesno('错误提示','上课周期与时间段不符,是否继续?')
                if yesno == False:
                        return False
      today=datetime.date.today() # 今天
      beforday=datetime.date(year,month,day) # 之前上课日期
      apartday=today.__sub__(beforday).days # 今天 减去 之前上课日期
      if apartday >= 7:# 如果大于7天确认是否操作
                yesno=messagebox.askyesno('确认操作', '离上课日期超过7天,是否继续?')
                if yesno == False:
                        return False
      courseDate=f'{str(year)}年{str(month)}月{str(day)}日'

      lst_mainMessage=
      tk_top.studentApprise(lst_mainMessage)
'''问卷调查'''
table_studentFinshed.bind('<Double-1>',showTest)

# 生成课评
def countApprisseLog(lst_eightAbility):
      appriseScore=0
      for i in range(0,max(lst_eightAbility)+1):
                appriseScore=appriseScore+lst_eightAbility.count(i)/len(lst_eightAbility)/((i+1)+(i)*0.25)
      if appriseScore >= 0.9:
                appriseScore='优秀'
      elif appriseScore >= 0.8:
                appriseScore='优良'
      elif appriseScore >= 0.7:
                appriseScore='良好'
      elif appriseScore >= 0.6:
                appriseScore='平常'
      else:
                appriseScore='有待提高'
      return appriseScore
'''八大能力评分公式'''
def saveApprise():
      tableSelected=table_studentFinshed.selection()

      dict_allquestion={}
      for eachSelected in tableSelected:
                tableValue=table_studentFinshed.item(eachSelected,option='values')
                studentName=tableValue
                courseName=tableValue
                if courseName in ['']:
                        messagebox.showinfo('提示','未查找到课程,请更新')
                        return False

                # 确定选项位置用
                if dict_allquestion == {}:
                        for eachQuestion in sql.getAllQuestion():
                              lst_option=[]
                              for i in range(6,15):
                                        if not eachQuestion in ['','\n',None]:
                                                lst_option.append(eachQuestion)
                              dict_allquestion]=lst_option

                # 统计结构及知识点数量用
                courseMessage=sql.getCourseMessage_courseName(courseName)
                lst_structure=courseMessage.split('|')
                lst_knowledge=courseMessage.split('|')

                # 获取日志
                appriseLog=sql.getAppriseLog_studentName_courseName(studentName,courseName)
                lst_questionLog=appriseLog
                lst_questionLog=re.sub('\'','"',lst_questionLog)
                lst_questionLog=re.sub('\n','',lst_questionLog)
                lst_questionLog=json.loads(lst_questionLog)

                # 处理评分和表现
                lst_focus=[]
                lst_selfConfident=[]
                lst_work=[]
                lst_deliver=[]
                lst_logic=[]
                lst_comprehension=[]
                lst_mood=[]
                lst_solve=[]
                str_goodDetail=''
                str_advice=''
                for eachQuestionLog in lst_questionLog:
                        # 获取选项位置
                        if eachQuestionLog['题型'] in ['单选题'] and eachQuestionLog['选择'] != ['']:
                              # print(eachQuestionLog['能力归类'],eachQuestionLog['题型'],dict_allquestion].index(eachQuestionLog['选择']),eachQuestionLog['细节描述'])
                              if eachQuestionLog['能力归类'] == '专注力':
                                        lst_focus.append(dict_allquestion].index(eachQuestionLog['选择']))
                              elif eachQuestionLog['能力归类'] == '自信心':
                                        lst_selfConfident.append(dict_allquestion].index(eachQuestionLog['选择']))
                              elif eachQuestionLog['能力归类'] == '动手能力':
                                        lst_work.append(dict_allquestion].index(eachQuestionLog['选择']))
                              elif eachQuestionLog['能力归类'] == '语言表达':
                                        lst_deliver.append(dict_allquestion].index(eachQuestionLog['选择']))
                              elif eachQuestionLog['能力归类'] == '逻辑思维':
                                        lst_logic.append(dict_allquestion].index(eachQuestionLog['选择']))
                              elif eachQuestionLog['能力归类'] == '理解能力':
                                        lst_comprehension.append(dict_allquestion].index(eachQuestionLog['选择']))
                              elif eachQuestionLog['能力归类'] == '情绪管理':
                                        lst_mood.append(dict_allquestion].index(eachQuestionLog['选择']))
                              elif eachQuestionLog['能力归类'] == '解决问题能力':
                                        lst_solve.append(dict_allquestion].index(eachQuestionLog['选择']))

                              # 细节
                              if dict_allquestion].index(eachQuestionLog['选择']) == 0 and not eachQuestionLog['细节描述'] in ['','\n',None]:
                                        str_goodDetail=str_goodDetail+'细节:'+eachQuestionLog['题目']+'\n选项:'+eachQuestionLog['选择']+'\n细节描述:'+eachQuestionLog['细节描述']+'\n\n'
                              else:
                                        if not eachQuestionLog['细节描述'] in ['','\n',None]:
                                                str_advice=str_advice+'细节:'+eachQuestionLog['题目']+'\n选项:'+eachQuestionLog['选择']+'\n细节描述:'+eachQuestionLog['细节描述']+'\n\n'

                        elif eachQuestionLog['题型'] in ['多选题']:
                              if eachQuestionLog['总序号'] in :
                                        leftKnowledge=len(lst_knowledge)-len( if i != ''])
                                        # print(eachQuestionLog['能力归类'],eachQuestionLog['题型'],leftKnowledge,eachQuestionLog['细节描述'])
                                        if eachQuestionLog['能力归类'] == '专注力':
                                                lst_focus.append(leftKnowledge)
                                        elif eachQuestionLog['能力归类'] == '自信心':
                                                lst_selfConfident.append(leftKnowledge)
                                        elif eachQuestionLog['能力归类'] == '动手能力':
                                                lst_selfConfident.append(leftKnowledge)
                                        elif eachQuestionLog['能力归类'] == '语言表达':
                                                lst_selfConfident.append(leftKnowledge)
                                        elif eachQuestionLog['能力归类'] == '逻辑思维':
                                                lst_selfConfident.append(leftKnowledge)
                                        elif eachQuestionLog['能力归类'] == '理解能力':
                                                lst_selfConfident.append(leftKnowledge)
                                        elif eachQuestionLog['能力归类'] == '情绪管理':
                                                lst_selfConfident.append(leftKnowledge)
                                        elif eachQuestionLog['能力归类'] == '解决问题能力':
                                                lst_selfConfident.append(leftKnowledge)

                                        if leftKnowledge == 0 and not eachQuestionLog['细节描述'] in ['','\n',None]:
                                                str_goodDetail=str_goodDetail+'细节:'+eachQuestionLog['题目']+'\n选项:'+','.join( if i != ''])+'\n细节描述:'+eachQuestionLog['细节描述']+'\n\n'
                                        else:
                                                if not eachQuestionLog['细节描述'] in ['','\n',None]:
                                                      str_advice=str_advice+'细节:'+eachQuestionLog['题目']+'\n选项:'+','.join( if i != ''])+'\n细节描述:'+eachQuestionLog['细节描述']+'\n\n'

                              elif eachQuestionLog['总序号'] in and if i != ''] != []:
                                        leftStructure=len(lst_structure)-len( if i != ''])
                                        # print(eachQuestionLog['能力归类'],eachQuestionLog['题型'],leftStructure,eachQuestionLog['细节描述'])
                                        if eachQuestionLog['能力归类'] == '专注力':
                                                lst_selfConfident.append(leftStructure)
                                        elif eachQuestionLog['能力归类'] == '自信心':
                                                lst_selfConfident.append(leftStructure)
                                        elif eachQuestionLog['能力归类'] == '动手能力':
                                                lst_selfConfident.append(leftStructure)
                                        elif eachQuestionLog['能力归类'] == '语言表达':
                                                lst_selfConfident.append(leftStructure)
                                        elif eachQuestionLog['能力归类'] == '逻辑思维':
                                                lst_selfConfident.append(leftStructure)
                                        elif eachQuestionLog['能力归类'] == '理解能力':
                                                lst_selfConfident.append(leftStructure)
                                        elif eachQuestionLog['能力归类'] == '情绪管理':
                                                lst_selfConfident.append(leftStructure)
                                        elif eachQuestionLog['能力归类'] == '解决问题能力':
                                                lst_selfConfident.append(leftStructure)

                                        if leftStructure == 0 and not eachQuestionLog['细节描述'] in ['','\n',None]:
                                                str_goodDetail=str_goodDetail+'细节:'+eachQuestionLog['题目']+'\n选项:'+','.join( if i != ''])+'\n细节描述:'+eachQuestionLog['细节描述']+'\n\n'
                                        else:
                                                if not eachQuestionLog['细节描述'] in ['','\n',None]:
                                                      str_advice=str_advice+'细节:'+eachQuestionLog['题目']+'\n选项:'+','.join( if i != ''])+'\n细节描述:'+eachQuestionLog['细节描述']+'\n\n'

                              else:
                                        if not eachQuestionLog['细节描述'] in ['','\n',None]:
                                                str_advice=str_advice+'细节:'+eachQuestionLog['题目']+'\n选项:'+','.join( if i != ''])+'\n细节描述:'+eachQuestionLog['细节描述']+'\n\n'

                        else:
                              if not eachQuestionLog['细节描述'] in ['','\n',None]:
                                        str_advice=str_advice+'细节:'+eachQuestionLog['题目']+'\n选项:'+eachQuestionLog['选择']+'\n细节描述:'+eachQuestionLog['细节描述']+'\n\n'

                appriseScore_focus=countApprisseLog(lst_focus)
                appriseScore_selfConfident=countApprisseLog(lst_selfConfident)
                appriseScore_work=countApprisseLog(lst_work)
                appriseScore_deliver=countApprisseLog(lst_deliver)
                appriseScore_logic=countApprisseLog(lst_logic)
                appriseScore_comprehension=countApprisseLog(lst_comprehension)
                appriseScore_mood=countApprisseLog(lst_mood)
                appriseScore_solve=countApprisseLog(lst_solve)

                # 获取日期
                year=entry_courseDate_year.get()
                month=entry_courseDate_month.get()
                day=entry_courseDate_day.get()
                year,month,day=int(year),int(month),int(day)
                xlsx_date=re.sub('-','',str(datetime.date(year,month,day)))
                xlsx_weekday=lst_week
               
                # 打开表格并填写基本信息
                wb_appriseLog=openpyxl.load_workbook('成长记录呈现形式.xlsx')
                ws_appriseLog=wb_appriseLog.active
                ws_appriseLog.cell(2,2).value=studentName
                ws_appriseLog.cell(2,4).value=courseName
                ws_appriseLog.cell(2,6).value=str(datetime.date(year,month,day))
                ws_appriseLog.cell(3,5).value=appriseScore_focus
                ws_appriseLog.cell(4,5).value=appriseScore_selfConfident
                ws_appriseLog.cell(5,5).value=appriseScore_work
                ws_appriseLog.cell(6,5).value=appriseScore_deliver
                ws_appriseLog.cell(7,5).value=appriseScore_logic
                ws_appriseLog.cell(8,5).value=appriseScore_comprehension
                ws_appriseLog.cell(9,5).value=appriseScore_mood
                ws_appriseLog.cell(10,5).value=appriseScore_solve
                ws_appriseLog.cell(12,1).value=str_goodDetail
                ws_appriseLog.cell(14,1).value=str_advice
                try:
                        wb_appriseLog.save(xlsx_date+xlsx_weekday+'-'+studentName+'-'+courseName+'.xlsx')
                except:
                        messagebox.showinfo('提示','请关闭已打开的表格')

      messagebox.showinfo('提示','选择的学生课评已生成完毕')

button_saveApprise=Button(main,text='生成课评',bg='black',fg='white',command=saveApprise)
button_saveApprise.place(x=10,y=270)

# 界面循环
main.mainloop()

三、主界面数据库格式


我是mysql数据库初学者,所以特地在某讯云上买了个轻量应用服务器数据库练手,存储的信息格式如下:









# 主界面从数据库获取信息的代码
import pymysql
import time, datetime
from sqlite3 import Cursor

# 连接数据库
mysql=pymysql.connect(
      host='外网地址',
      port=23445,
      user='数据库账号',
      password='数据库密码',
      database='studentApprise'
)
cursor=mysql.cursor()

def getTeacherMessage():
cursor.execute("SELECT * FROM teacherMessage")
rep=cursor.fetchall()
return rep
'''主界面,获取老师信息'''

def getStudentMessage(teacherName,courseTime):
teacherName="'%s'" % teacherName
courseTime="'%s'" % courseTime
cursor.execute("SELECT * FROM studentMessage WHERE 任课教师 = " + teacherName + " AND 时间段 = " + courseTime)
rep=cursor.fetchall()
return rep
'''主界面,根据老师和时间段获取学生信息'''

def getCourseMessage_courseLevel(courseLevel):
courseLevel="'%s'" % courseLevel
cursor.execute("SELECT * FROM courseMessage WHERE 阶段 = " + courseLevel)
rep=cursor.fetchall()
return rep
'''主界面,根据阶段获取课程'''

def getAppriseLog_studentName_courseName(studentName,courseName):
studentName="'%s'" % studentName
courseName="'%s'" % courseName
cursor.execute("SELECT * FROM appriseLog WHERE 学生姓名 = " + studentName + " AND 上课课程 = " + courseName)
rep=cursor.fetchall()
return rep
'''主界面,根据学生获取日志'''

四、分界面



需要实现的功能:
1、选择出勤状态,如果忘记选择了却点击保存课评,提示是否默认为出勤状态
2、八大步骤所有的问题和选项都能通过修改数据库而在分界面根据题目类型(单选、多选)来显示
3、还有其他很多小细节,比如Frame界面不能实现鼠标滚轮进行滚动,需要先添加Canvas画布再放上去等等,希望通过最简单又容易维护的方法来完成这个程序。

# encoding='utf-8'
# 分界面代码
import sql # 自己写的库
import re

import tkinter
from tkinter import ttk
from tkinter import messagebox
from tkinter import scrolledtext
from tkinter import *

class studentApprise:
      def __init__(self,lst_mainMessage):
                self.studentName=lst_mainMessage
                self.courseTeacher=lst_mainMessage
                self.courseName=lst_mainMessage
                self.proxyTeacher=lst_mainMessage
                self.courseDate=lst_mainMessage
                self.courseWeek=lst_mainMessage
                self.lst_question=[]

                self.top=tkinter.Toplevel()
                self.top.title('问卷调查') # 学生名字
                self.top.geometry('960x1005+950+0')
                self.StudentMessage()
                self.appriseMessage_frame()
                self.top.mainloop()
      '''基本数据'''

      def StudentMessage(self):
                # 姓名标签
                x_studentName=10
                y_stduentName=10
                label_student=Label(self.top,text='学生姓名:')
                label_student.place(x=x_studentName,y=y_stduentName)
                label_studentName=Label(self.top,text=self.studentName,fg='green')
                label_studentName.place(x=x_studentName+60,y=y_stduentName)

                # 上课日期
                x_courseDate=10
                y_courseDate=30
                label_date=Label(self.top,text='上课日期:')
                label_date.place(x=x_courseDate,y=y_courseDate)
                label_courseDate=Label(self.top,text=f'{self.courseDate}-{self.courseWeek}',fg='green')
                label_courseDate.place(x=x_courseDate+60,y=y_courseDate)

                # 上课课程
                x_courseName=10
                y_courseName=50
                label_course=Label(self.top,text='上课课程:')
                label_course.place(x=x_courseName,y=y_courseName)
                label_courseName=Label(self.top,text=self.courseName,fg='green')
                label_courseName.place(x=x_courseName+60,y=y_courseName)

                # 任课教师
                x_courseTeacher=10
                y_courseTeacher=70
                label_teacher=Label(self.top,text='任课教师:')
                label_teacher.place(x=x_courseTeacher,y=y_courseTeacher)
                label_courseTeacher=Label(self.top,text=self.courseTeacher,fg='blue')
                label_courseTeacher.place(x=x_courseTeacher+60,y=y_courseTeacher)

                # 代课教师
                x_proxyTeacher=10
                y_proxyTeacher=90
                label_proxy=Label(self.top,text='代课教师:')
                label_proxy.place(x=x_proxyTeacher,y=y_proxyTeacher)
                label_proxyTeacher=Label(self.top,text=self.proxyTeacher,fg='blue')
                label_proxyTeacher.place(x=x_proxyTeacher+60,y=y_proxyTeacher)

                # 出勤状态
                x_AttendanceStatus=200
                y_AttendanceStatus=10
                label_AttendanceStatus=Label(self.top,text='出勤状态:')
                label_AttendanceStatus.place(x=x_AttendanceStatus,y=y_AttendanceStatus)
                self.radioButton_AttendanceStatus=StringVar()
                AttendanceStatus1=Radiobutton(self.top,text="出勤",variable=self.radioButton_AttendanceStatus,value="出勤")
                AttendanceStatus1.place(x=x_AttendanceStatus+60,y=y_AttendanceStatus)
                AttendanceStatus2=Radiobutton(self.top,text="未出勤",variable=self.radioButton_AttendanceStatus,value="未出勤")
                AttendanceStatus2.place(x=x_AttendanceStatus+120,y=y_AttendanceStatus)
                AttendanceStatus3=Radiobutton(self.top,text="补课",variable=self.radioButton_AttendanceStatus,value="补课")
                AttendanceStatus3.place(x=x_AttendanceStatus+190,y=y_AttendanceStatus)

                # 问卷按钮
                x_button=10
                y_button=120
                def topmost1():
                        self.frame1.tkraise()
                        button1.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def topmost2():
                        self.frame2.tkraise()
                        button2.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def topmost3():
                        self.frame3.tkraise()
                        button3.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def topmost4():
                        self.frame4.tkraise()
                        button4.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def topmost5():
                        self.frame5.tkraise()
                        button5.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def topmost6():
                        self.frame6.tkraise()
                        button6.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def topmost7():
                        self.frame7.tkraise()
                        button7.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def topmost8():
                        self.frame8.tkraise()
                        button8.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def topmost9():
                        self.frame9.tkraise()
                        button9.config(bg='orange',fg='white')
                        self.canvas.yview("moveto",0)
                def savequestion():
                        AttendanceStatus=self.radioButton_AttendanceStatus.get()
                        if AttendanceStatus in ['']:
                              yesno=messagebox.askyesno('提示', '考勤状态未确认,是否默认为出勤')
                              if yesno == False:
                                        return False
                              else:
                                        AttendanceStatus='出勤'
                        i=0
                        for eachQuestion in self.lst_question:
                        # {'总序号':eachQuestion,'题目序号':eachQuestion,'流程':eachQuestion,'能力归类':eachQuestion,'题型':eachQuestion,'题目':eachQuestion,'选择':[],'细节描述':''}
                              lst_getOptionValue=[]
                              for eachOption in eachQuestion['选择']:
                                        lst_getOptionValue.append(eachOption.get())
                              questionDetail=eachQuestion['细节描述'].get('1.0',END)
                              self.lst_question['选择']=lst_getOptionValue
                              self.lst_question['细节描述']=questionDetail
                              i=i+1
                        courseDate_new=re.sub('日.*','',self.courseDate)
                        courseDate_new=re.sub('年|月','-',courseDate_new)
                        lst_question_new=re.sub('\'','\\\'',str(self.lst_question))
                        try:
                              sql.inAppriseLog(self.studentName,courseDate_new,self.courseName,self.courseTeacher,self.proxyTeacher,AttendanceStatus,lst_question_new)
                              messagebox.showinfo('提示','保存成功')
                              self.top.destroy()
                        except Exception as e:
                              messagebox.showinfo('提示','数据存储错误,请联系管理员\n'+str(e))

                '''获取选择选项及细节描述'''
                button1=Button(self.top,text='上课前',bd=3,width=13,command=topmost1)
                button1.place(x=x_button,y=y_button)
                button2=Button(self.top,text='上课中-打招呼',bd=3,width=13,command=topmost2)
                button2.place(x=x_button+105,y=y_button)
                button3=Button(self.top,text='上课中-引导主题',bd=3,width=13,command=topmost3)
                button3.place(x=x_button+210,y=y_button)
                button4=Button(self.top,text='上课中-分析结构',bd=3,width=13,command=topmost4)
                button4.place(x=x_button+315,y=y_button)
                button5=Button(self.top,text='上课中-设计图',bd=3,width=13,command=topmost5,bg='pink')
                button5.place(x=x_button+420,y=y_button)
                button6=Button(self.top,text='上课中-搭建',bd=3,width=13,command=topmost6)
                button6.place(x=x_button+525,y=y_button)
                button7=Button(self.top,text='上课中-编程',bd=3,width=13,command=topmost7,bg='pink')
                button7.place(x=x_button+630,y=y_button)
                button8=Button(self.top,text='上课中-介绍',bd=3,width=13,command=topmost8)
                button8.place(x=x_button+735,y=y_button)
                button9=Button(self.top,text='下课后',bd=3,width=13,command=topmost9)
                button9.place(x=x_button+840,y=y_button)
                button10=Button(self.top,text='保存课评',bd=3,width=13,command=savequestion)
                button10.place(x=10,y=970)
      '''显示学生基本信息'''

      def buildQustion(self,choiceFrame,repFromSqlByQuestion):
                x_question=10
                y_question=10
                for eachQuestion in repFromSqlByQuestion: # (101, 1, '上课前', '情绪管理', '单选题', '孩子到校心情:', '兴高采烈', '一般', '抗拒上课', '心情不好', '', '', '', '')
                        if eachQuestion == '单选题':
                              question=f'{str(eachQuestion)}、({eachQuestion}){eachQuestion}'
                              self.lst_question.append({'总序号':eachQuestion,'题目序号':eachQuestion,'流程':eachQuestion,'能力归类':eachQuestion,'题型':eachQuestion,'题目':eachQuestion,'选择':[]})
                              label_question=Label(choiceFrame,text=question)
                              label_question.place(x=x_question,y=y_question)
                              y_question=y_question+30
                              self.radioButton_question=StringVar()
                              self.lst_question[-1]['选择'].append(self.radioButton_question)
                              for i in range(6,14):
                                        option=eachQuestion
                                        if option in ['',None]:
                                                continue
                                        question_option=Radiobutton(choiceFrame,text=option,variable=self.radioButton_question,value=option,tristatevalue=0)
                                        question_option.place(x=x_question+20,y=y_question)
                                        y_question=y_question+30
                        elif eachQuestion == '多选题':
                              question=f'{str(eachQuestion)}、({eachQuestion}){eachQuestion}'
                              self.lst_question.append({'总序号':eachQuestion,'题目序号':eachQuestion,'流程':eachQuestion,'能力归类':eachQuestion,'题型':eachQuestion,'题目':eachQuestion,'选择':[]})
                              label_question=Label(choiceFrame,text=question)
                              label_question.place(x=x_question,y=y_question)
                              y_question=y_question+30
                              courseMessage=sql.getCourseMessage_courseName(self.courseName)
                              lst_structure=courseMessage.split('|')
                              lst_points=courseMessage.split('|')

                              if question in ['2、(逻辑思维)能否分析以下完整结构:','1、(逻辑思维)基本结构和功能结构是否完整:','4、(解决问题能力)作品是否有以下基本结构及功能结构']:
                                        for eachStructure in lst_structure:
                                                self.CheckButton_question=StringVar()
                                                self.lst_question[-1]['选择'].append(self.CheckButton_question)
                                                question_option=Checkbutton(choiceFrame,text=eachStructure,variable=self.CheckButton_question,onvalue=eachStructure,tristatevalue=0)
                                                question_option.place(x=x_question+20,y=y_question)
                                                y_question=y_question+30

                              elif question in ['4、(理解能力)能否清楚以下知识:']:
                                        for eachPoint in lst_points:
                                                self.CheckButton_question=StringVar()
                                                self.lst_question[-1]['选择'].append(self.CheckButton_question)
                                                question_option=Checkbutton(choiceFrame,text=eachPoint,variable=self.CheckButton_question,onvalue=eachPoint,tristatevalue=0)
                                                question_option.place(x=x_question+20,y=y_question)
                                                y_question=y_question+30

                        label_detail=Label(choiceFrame,text='细节描述:')
                        label_detail.place(x=x_question+20,y=y_question)
                        entry_detail=Text(choiceFrame,width=50,height=3)
                        entry_detail.place(x=x_question+90,y=y_question)
                        self.lst_question[-1]['细节描述']=entry_detail
                        y_question=y_question+60
      '''创建题目和选项'''

      def appriseMessage_frame(self):
                def OnMouseWheel(event):
                        self.canvas.yview_scroll(int(-1*(event.delta/120)),"units")
                        return "break"
                '''鼠标滚动'''

                self.canvas=Canvas(self.top,width=910,height=800)
                self.canvas.place(x=10,y=160)

                sbar=Scrollbar(self.top)
                sbar.place(x=930,y=160,width=20,height=800)

                self.frame1=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame1.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame1,anchor="nw")
                self.frame1.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion1=sql.getQuestion('上课前')
                studentApprise.buildQustion(self,self.frame1,repFromSqlByQuestion1)

                self.frame2=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame2.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame2,anchor="nw")
                self.frame2.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion2=sql.getQuestion('上课中-打招呼')
                studentApprise.buildQustion(self,self.frame2,repFromSqlByQuestion2)

                self.frame3=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame3.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame3,anchor="nw")
                self.frame3.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion3=sql.getQuestion('上课中-引导主题')
                studentApprise.buildQustion(self,self.frame3,repFromSqlByQuestion3)

                self.frame4=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame4.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame4,anchor="nw")
                self.frame4.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion4=sql.getQuestion('上课中-分析结构')
                studentApprise.buildQustion(self,self.frame4,repFromSqlByQuestion4)

                self.frame5=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame5.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame5,anchor="nw")
                self.frame5.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion5=sql.getQuestion('上课中-设计图')
                studentApprise.buildQustion(self,self.frame5,repFromSqlByQuestion5)

                self.frame6=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame6.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame6,anchor="nw")
                self.frame6.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion6=sql.getQuestion('上课中-搭建')
                studentApprise.buildQustion(self,self.frame6,repFromSqlByQuestion6)

                self.frame7=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame7.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame7,anchor="nw")
                self.frame7.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion7=sql.getQuestion('上课中-编程')
                studentApprise.buildQustion(self,self.frame7,repFromSqlByQuestion7)

                self.frame8=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame8.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame8,anchor="nw")
                self.frame8.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion8=sql.getQuestion('上课中-介绍')
                studentApprise.buildQustion(self,self.frame8,repFromSqlByQuestion8)

                self.frame9=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame9.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame9,anchor="nw")
                self.frame9.bind("<MouseWheel>", OnMouseWheel)
                repFromSqlByQuestion9=sql.getQuestion('下课后')
                studentApprise.buildQustion(self,self.frame9,repFromSqlByQuestion9)

                self.frame10=Frame(self.canvas,width=910,height=3000,highlightthickness=1,highlightbackground='black')
                self.frame10.place(x=0,y=0)
                self.canvas.create_window((0,0),window=self.frame10,anchor="nw")
                self.frame10.bind("<MouseWheel>", OnMouseWheel)

                self.canvas.configure(yscrollcommand=sbar.set, scrollregion=self.canvas.bbox("all"))
                sbar.config(command=self.canvas.yview)
      '''创建题目框'''

if __name__ == '__main__':
# 测试
      lst_mainMessage=['xxx', 'xxx', '机械抓手', '无', '2023年3月3日', '周五']
      studentApprise=studentApprise(lst_mainMessage)

五、分界面数据库格式





# 分界面获取数据库信息的代码
def getQuestion(flowPath):
      flowPath="'%s'" % flowPath
      cursor.execute("SELECT * FROM question WHERE 流程 = " + flowPath)
      rep=cursor.fetchall()
      return rep
'''分界面,根据流程获取问题'''

def getAllQuestion():
      cursor.execute("SELECT * FROM question")
      rep=cursor.fetchall()
      return rep
'''分界面,获取所有问题'''

def getCourseMessage_courseName(courseName):
      courseName="'%s'" % courseName
      cursor.execute("SELECT * FROM courseMessage WHERE 课程 = " + courseName)
      rep=cursor.fetchall()
      return rep
'''分界面,根据课程名获取课程'''

def inAppriseLog(studentName,courseDate,courseName,courseTeacher,proxyTeacher,AttendanceStatus,appriseLog):
      appriseDate=str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
      query="INSERT INTO `appriseLog` (`存储日期`, `学生姓名`, `上课日期`, `上课课程`, `任课教师`, `代课教师`, `出勤状态`, `记录`) VALUES ('{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}');".format(appriseDate, studentName, courseDate, courseName, courseTeacher, proxyTeacher, AttendanceStatus, appriseLog)
      cursor.execute(query)
      mysql.commit()
'''分界面,保存问答记录'''

六、效果展示及总结


在主界面点击生成课评后,会生成一个EXCEL表格,直接复制粘贴到微信就可以发给家长了,效果如下:


总结:
有一个功能是我没有实现到的,就是分界面填写完问答后,应该在主界面刷新一下问答记录,但是我没找到适合的方法,只能通过手动双击刷新来实现。
也有部分代码在对信息进行判断的时候,没有顾虑周全,会导致新增的题目和选项以错误的方式进行展示。
不过这也是我在学习数据库之后的一个练手项目,相信以后会考虑的更加周全。

狐白本白 发表于 2023-3-21 17:07

本帖最后由 狐白本白 于 2023-3-21 17:14 编辑

from tkinter import *
import time
def updatetimer():
    timer=time.strftime("%H:%M:%S")
    timelabel.configure(text=timer)
    timelabel.after(1000,updatetimer)
root=Tk()
timelabel=Label(root)
timelabel.pack()
timelabel.after(1000,updatetimer)
root.mainloop()
大佬很牛针对你最后一个问题我的想法是 可以记录一下分界面打开 关键字0(关闭) 1(打开) 当由0进入1 准备执行def当由1变为0 程序自动执行刷新按钮
或者可以写个time 定时刷新
只是个思路毕竟我也不知道有啥方法

WOSHINIDIE666 发表于 2023-3-30 18:33

刚毕业那年就去做了编程老师那会还在玛酷结果遇上疫情无奈进厂现在想想那会过的真快乐,每天陪陪孩子上课也很开心时过境迁看到曾经的同行感触良多优秀啊这位老师。

adsl133 发表于 2023-3-21 16:13

谢谢分享。支持一个。

sdvip168 发表于 2023-3-21 16:29

感谢楼主分享

wang2223130 发表于 2023-3-21 16:32

谢谢分享

ZuanJian 发表于 2023-3-21 16:36

必须支持原创啊!

abc2018zh 发表于 2023-3-21 16:45

功能适用性强,替老师们节省很多时间{:1_921:}

xisuo67 发表于 2023-3-21 16:50

感谢分享,写的非常详细

Wuai6268 发表于 2023-3-21 16:59

看这挺不错,支持支持

hu007 发表于 2023-3-21 17:15

很好的分享.谢谢!
页: [1] 2 3 4 5 6 7 8 9
查看完整版本: 机器人老师做一个记录孩子上课表现的程序