Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)

本文的单项选择题与管理系统通过面向对象实现,调用tkinter完成了基本GUI界面,文件存储方面采用txt格式化存储、读取数据,主要功能围绕基本的“增删改查”展开,详细的程序介绍可以私聊我本人获取ppt和实验报告,仅供学习和参考,转载需标明出处。

以下是部分效果图

Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第1张图片 

 管理员密码默认为123456,后续可以在代码里更改管理员密码。

Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第2张图片

 Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第3张图片

需要特别注意的是,目前程序仍存在一定的弊端,例如题目信息如果过长,就会影响到布局,建议不要录入题目信息或选项信息过长的题目,也可以根据具体需求,自行改到代码。

Part1:程序框架设计

Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第4张图片

 

程序框架设计上,我设计了三个类,其中两个类用来封装数据,一个类用来封装方法,如上所示图表,Problem类封装了试题的题号、题目、选项A、B、C、D、正确答案这些数据,Student类中我们有学生的用户名、账号、密码、成绩、答题时间这些成员,Manage类中封装了我们程序所需要的方法,程序整体结构分明,层次清晰,代码规范整齐。

其中,save_information方法和read_information方法之后我将着重讲解,log_in和student_login方法通过同样的底层逻辑实现,都是对循环遍历的运用来判断登录成功的条件是否满足,add_problem方法和del_problem、del_student方法是系统操作最常见的“增删查改”四大操作的“增和删”,通过input函数输入该输入的信息,将输入的信息整体打包成一个字典,字典特有的key值之后会帮助我们很好的提取所需要的数据,再将字典append到学生/试卷列表中,实现添加。而rank_student方法和analysis_student方法是对学生成绩的基本处理,其中涉及到利用sorted函数对列表实现快速排序,最后的test_begin先向函数传递学生姓名的参数,再循环遍历文件中的试题信息,来判断你的答案是否正确并计分,最后遍历文件中的学生信息来匹配函数接受到的学生姓名,将计分的成绩更新到学生的信息中,此外,还调用了time库来记录学生的答题时间信息。

Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第5张图片

   test_begin方法的实现

Part2:文件读取和写入

存储文件的时候,由于我们只能向文件写入str类型的数据,而在程序中,我们文件里的数据是放在了一个字典嵌套的列表中的,为了方便我们读取数据,我们在写入数据时,每两个数据中我们写入一个逗号作为整个字符串的分隔符。

读取数据的时候,我们读取的初始数据是一个字符串,用split函数初步处理后,就变成了一个列表,但此时还没有满足我们所需要的字典嵌套列表,所以我们进一步将整个列表按照字典的需求分成一个个的字典,在放到一个新的列表中,此时的新列表就能满足我们的使用需求。以下的图示以学生信息的读取和写入为例。

 Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第6张图片

 

文件读取的实现

Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第7张图片

文件写入的实现

 

为了进一步理解文件读取这一部分的实现,我们设计了以下的流程图来帮助我们更生动形象的理解数据从文件到我们所需要的要求所经历过的步骤。如下图所示。

数据的处理过程

Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第8张图片

Part3:GUI设计

在GUI设计方面,我们通过tkinter库来实现,tkinter是python的内置库是一套完整的GUI开发模块的组合或套件,这些模块共同提供了强大的跨平台GUI编程的功能,所有的源码文件位于Python安装目录中lib\tkinter文件夹。

tkinter与turtle类似,无需额外安装,使用起来非常方便。tkinter提供了很多控件和消息事件,可以很快入手,非常适合开发具有界面的轻量级应用程序。

Python课程设计——单项选择题答题与管理系统(已利用tkinter库实现图形化界面)_第9张图片

图形化界面

在布局方面,我采用了place的布局方式,同时,在答题功能的图形化过程中,还引入了frame框架来实现滑块和文本框的联动,初步掌握了GUI的布局设计,了解到事件的处理、控件之间的命令的运行逻辑。

 

以下是完整的程序代码

系统设计部分:

import os
import time


class Problem:  # 定义试题信息的类
    def __init__(self, num, question, choice_a, choice_b, choice_c, choice_d, answer):
        self.num = num
        self.question = question
        self.choice_a = choice_a
        self.choice_b = choice_b
        self.choice_c = choice_c
        self.choice_d = choice_d
        self.answer = answer


class Student:  # 定义学生信息的类
    def __init__(self, name, user_name, user_password, grade, usetime):
        self.name = name
        self.user_name = user_name
        self.user_password = user_password
        self.grade = grade
        self.usetime = usetime


# 基本功能都由这个类的方法实现
class Manage:
    def __init__(self):
        self.StudentInfo = []
        self.ProblemInfo = []

    @staticmethod
    def main_menu():
        print("***************")
        print("1.管理员端登录")
        print("2.学生端登录")
        print("3.注册学生端账户")
        print("4.退出系统")
        print("***************")

    @staticmethod
    def administrator_menu():
        print("***************")
        print("1.录入试题信息")
        print("2.查看学生信息")
        print("3.排名学生成绩")
        print("4.查看试题信息")
        print("5.分析总体答题情况")
        print("6.删除学生信息")
        print("7.删除试题信息")
        print("8.返回上级")
        print("***************")

    @staticmethod
    def student_menu():
        print("***************")
        print("1.开始答题")
        print("2.返回上级")
        print("***************")

    @staticmethod
    def log_in():
        psw = int(input("请输入管理员密码"))
        if psw == 123456:
            Manage.administrator_menu()
            while 1:
                operate_administrator = int(input("请输入要选择的操作"))
                if operate_administrator == 1:
                    Manage.add_problem(start)
                    Manage.administrator_menu()
                if operate_administrator == 2:
                    Manage.show_student(start)
                if operate_administrator == 3:
                    Manage.rank_student(start)
                if operate_administrator == 4:
                    Manage.show_problem(start)
                if operate_administrator == 5:
                    Manage.analysis_student(start)
                if operate_administrator == 6:
                    Manage.del_student(start)
                if operate_administrator == 7:
                    Manage.del_problem(start)
                if operate_administrator == 8:
                    Manage.main_menu()
                    return
        else:
            print("账号或密码错误,已返回上级!")
            Manage.main_menu()

    def register(self):
        print("***************")
        new_student = Student(name=input("输入你的用户名"),
                              user_name=input("输入你的账号"),
                              user_password=input("输入你的密码"),
                              grade="暂无成绩",
                              usetime="暂无信息")
        temp = {"用户名": new_student.name, "账号": new_student.user_name, "密码": new_student.user_password,
                "成绩": new_student.grade, "答题时间": new_student.usetime}
        # 这里的new_student不能直接传入列表,要放在一个字典里把数据”打包“过去
        self.StudentInfo.append(temp)
        print("注册成功!")
        self.save_information()
        self.main_menu()

    def student_login(self):
        print("***************")
        temp1 = input("请输入你的账号")
        temp2 = input("请输入你的密码")
        if len(self.StudentInfo) == 0:
            # 如果学生信息为空,说明还没有账号注册,当作账号或密码错误处理
            print("账号或密码错误!已返回上级")
            self.main_menu()
            return
        for stu in self.StudentInfo:  # 循环遍历列表判断账号和密码是否正确
            if stu["账号"] == temp1 and stu["密码"] == temp2:
                print("登录成功!欢迎你%s同学" % (stu["用户名"]))
                self.student_menu()
                while 1:
                    operate_student = int(input("请输入要选择的操作"))
                    if operate_student == 1:
                        self.test_begin(stu["用户名"])
                        self.main_menu()
                        return
                    if operate_student == 2:
                        self.main_menu()
                        return
        else:
            print("账号或密码错误!已返回上级")
            self.main_menu()

    def add_problem(self):
        new_problem = Problem(num=input("输入题号"),
                              question=input("输入题目"),
                              choice_a=input("输入选项A"),
                              choice_b=input("输入选项B"),
                              choice_c=input("输入选项C"),
                              choice_d=input("输入选项D"),
                              answer=input("输入正确答案"))
        temp = {"题号": new_problem.num, "题目": new_problem.question, "选项A": new_problem.choice_a,
                "选项B": new_problem.choice_b, "选项C": new_problem.choice_c, "选项D": new_problem.choice_d,
                "正确答案": new_problem.answer}
        self.ProblemInfo.append(temp)
        # 和学生信息一样,试题信息也要打包在一个字典里面后添加到列表
        print("录入成功!")
        self.save_information()

    def del_student(self):
        user_name = input("输入要删除的学生账号")
        index = 0
        for stu in self.StudentInfo:
            if stu["账号"] == user_name:
                del self.StudentInfo[index]
                self.save_information()
                print("删除成功")
                self.administrator_menu()
                return
            index += 1
        print("未查询到学生信息!")
        self.administrator_menu()
        return

    def del_problem(self):
        num = input("输入要删除的题目题号")
        index = 0
        for pro in self.ProblemInfo:
            if pro["题号"] == num:
                del self.ProblemInfo[index]
                self.save_information()
                print("删除成功")
                self.administrator_menu()
                return
            index += 1
        print("未查询到试题信息!")
        self.administrator_menu()
        return

    def show_student(self):
        if len(self.StudentInfo) == 0:
            print("暂无学生信息")
            self.administrator_menu()
            return
        for stu in self.StudentInfo:
            print(stu)
        input("按任意键继续")
        self.administrator_menu()
        return

    def show_problem(self):
        if len(self.ProblemInfo) == 0:
            print("暂无试题信息")
        for pro in self.ProblemInfo:
            print("%s:%s\n"
                  "A.%s\n"
                  "B.%s\n"
                  "C.%s\n"
                  "D.%s\n"
                  "正确答案:%s"
                  % (pro["题号"], pro["题目"], pro["选项A"], pro["选项B"], pro["选项C"], pro["选项D"],
                     pro["正确答案"]))
        input("按任意键继续")
        self.administrator_menu()
        return

    def test_begin(self, name):
        # 答题功能的主要功能由循坏遍历列表和time模板实现
        if len(self.ProblemInfo) == 0:
            print("暂无试题信息")
            self.student_menu()
            return
        grade = 0
        print("Test Begin!")
        start_time = time.time()
        for pro in self.ProblemInfo:
            print("%s:%s\n"
                  "A.%s\n"
                  "B.%s\n"
                  "C.%s\n"
                  "D.%s\n"
                  % (pro["题号"], pro["题目"], pro["选项A"], pro["选项B"], pro["选项C"], pro["选项D"]))
            answer = input("输入你的答案")
            if answer == pro["正确答案"]:
                grade += 5
        end_time = time.time()
        for stu in self.StudentInfo:
            if stu["用户名"] == name:
                stu["成绩"] = str(grade)
                stu["答题时间"] = str(int((end_time - start_time)))
                break
        print("Test Over!\n你的成绩是%d分,用时%d秒" % (grade, end_time - start_time))
        self.save_information()
        return

    def rank_student(self):
        if len(start.StudentInfo) == 0:
            print("暂无学生信息")
            return
        tool = self.StudentInfo
        for del_zero in tool:
            if del_zero["成绩"] == "暂无成绩":
                del_zero["成绩"] = -1
        temp = sorted(tool, key=lambda x: int(x["成绩"]), reverse=True)
        rank = 1
        for stu in temp:
            if stu["成绩"] == -1:
                stu["成绩"] = "暂无成绩"
            print("第%d名:%s %s分 用时%s秒" % (rank, stu["用户名"], stu["成绩"], stu["答题时间"]))
            rank += 1
        input("按任意键继续")
        self.administrator_menu()
        return

    def analysis_student(self):
        # 分析参加考试的人数,平均分
        if len(self.StudentInfo) == 0:
            print("暂无答题信息")
            self.administrator_menu()
            return
        print("本次测试有%d道题目" % (len(self.ProblemInfo)))
        print("满分%d分" % (len(self.ProblemInfo) * 5))
        student_num = 0
        total = 0
        for stu in self.StudentInfo:
            if stu["成绩"] == "暂无成绩":
                continue
            total += int(stu["成绩"])
            student_num += 1
        if student_num == 0:
            print("暂无答题信息")
            self.administrator_menu()
            return
        print("参与测试%d人" % student_num)
        print("平均分:%0.2f" % (total / student_num))
        input("按任意键继续")
        self.administrator_menu()
        return

    def save_information(self):  # 以字符串的数据类型向文件中写入
        with open("StudentInfo.txt", "w", encoding="utf_8") as fp:
            for stu in self.StudentInfo:
                fp.write(stu["用户名"])
                fp.write(",")
                fp.write(stu["账号"])
                fp.write(",")
                fp.write(stu["密码"])
                fp.write(",")
                fp.write(stu["成绩"])
                fp.write(",")
                fp.write(stu["答题时间"])
                fp.write(",")
            fp.close()  # 写入的时候数据之间用”,“分割开,读取的时候再用split函数分割分别读取
        with open("ProblemInfo.txt", "w", encoding="utf_8") as fp1:
            for pro in self.ProblemInfo:
                fp1.write(pro["题号"])
                fp1.write(",")
                fp1.write(pro["题目"])
                fp1.write(",")
                fp1.write(pro["选项A"])
                fp1.write(",")
                fp1.write(pro["选项B"])
                fp1.write(",")
                fp1.write(pro["选项C"])
                fp1.write(",")
                fp1.write(pro["选项D"])
                fp1.write(",")
                fp1.write(pro["正确答案"])
                fp1.write(",")
            fp1.close()
        return

    def read_information(self):
        if not os.path.exists("StudentInfo.txt"):
            print("暂无学生信息,跳过读取!")
        else:
            with open("StudentInfo.txt", "r", encoding="utf_8") as fp:
                stu = fp.read()
                stu = stu.split(",")  # 文件的字符串split后变成列表类型,再通过列表循环读取,每次读取一批数据打包成一个字典,再append到程序当前存储信息的列表中
                stu.pop()
                for i in range(len(stu) // 5):
                    stu_pass = {"用户名": stu[5 * i + 0],
                                "账号": stu[5 * i + 1],
                                "密码": stu[5 * i + 2],
                                "成绩": stu[5 * i + 3],
                                "答题时间": stu[5 * i + 4]}
                    self.StudentInfo.append(stu_pass)
                fp.close()
            print("学生信息读取成功!")

        if not os.path.exists("ProblemInfo.txt"):
            print("暂无试卷信息,跳过读取!")
        else:
            with open("ProblemInfo.txt", "r", encoding="utf_8") as fp1:
                pro = fp1.read()
                pro = pro.split(",")
                pro.pop()
                for j in range(len(pro) // 7):
                    pro_pass = {"题号": pro[7 * j + 0],
                                "题目": pro[7 * j + 1],
                                "选项A": pro[7 * j + 2],
                                "选项B": pro[7 * j + 3],
                                "选项C": pro[7 * j + 4],
                                "选项D": pro[7 * j + 5],
                                "正确答案": pro[7 * j + 6]}
                    self.ProblemInfo.append(pro_pass)
                fp1.close()
            print("试卷信息读取成功!")


start = Manage()

 GUI设计部分:

import time
import tkinter as tk
import SystemDesign

start = SystemDesign.Manage()
start.read_information()


# root:主菜单   root2:管理员菜单    root3:管理员登录界面   root4:学生登陆界面
def administrator_menu():
    root.withdraw()
    root2 = tk.Tk()
    root2.title("单项选择题答题与管理系统")
    root2.geometry("900x700")
    root2.config(background='pink')
    bt1 = tk.Button(root2, text='1.录入试题信息', font=("Helvetica", 30), background='pink',
                    command=lambda: func_ad_1(root2))
    bt1.place(x=300, y=20)
    bt2 = tk.Button(root2, text='2.查看学生信息', font=("Helvetica", 30), background='pink',
                    command=lambda: func_ad_2(root2))
    bt2.place(x=300, y=100)
    bt3 = tk.Button(root2, text='3. 排名学生成绩', font=("Helvetica", 30), background='pink',
                    command=lambda: func_ad_3(root2))
    bt3.place(x=300, y=180)
    bt4 = tk.Button(root2, text='4.查看试题信息', font=("Helvetica", 30), background='pink',
                    command=lambda: func_ad_4(root2))
    bt4.place(x=300, y=260)
    bt5 = tk.Button(root2, text='5.分析总体答题情况', font=("Helvetica", 30), background='pink',
                    command=lambda: func_ad_5(root2))
    bt5.place(x=300, y=340)
    bt6 = tk.Button(root2, text='6.删除试题信息', font=("Helvetica", 30), background='pink',
                    command=lambda: func_ad_6(root2))
    bt6.place(x=300, y=420)
    bt7 = tk.Button(root2, text='7.删除学生信息', font=("Helvetica", 30), background='pink',
                    command=lambda: func_ad_7(root2))
    bt7.place(x=300, y=500)
    bt8 = tk.Button(root2, text='8.返回上级', font=("Helvetica", 30), background='pink',
                    command=lambda: func_ad_8(root2))
    bt8.place(x=300, y=580)


def func_ad_1(x):  # 管理员功能一
    x.destroy()
    root_func1 = tk.Tk()
    root_func1.title("单项选择题答题与管理系统")
    root_func1.geometry("900x700")
    root_func1.config(background='pink')
    func1title = tk.Label(root_func1, text="输入你的试题信息", font=("Helvetica", 40), background="pink")
    func1title.pack()

    func1_lb1 = tk.Label(root_func1, text="题号", font=("Helvetica", 20), background="pink")
    func1_lb1.place(x=220, y=80)
    func1_entry1 = tk.Entry(root_func1, width=45)
    func1_entry1.place(x=320, y=90)

    func1_lb2 = tk.Label(root_func1, text="题目", font=("Helvetica", 20), background="pink")
    func1_lb2.place(x=220, y=120)
    func1_entry2 = tk.Entry(root_func1, width=45)
    func1_entry2.place(x=320, y=130)

    func1_lb3 = tk.Label(root_func1, text="选项A", font=("Helvetica", 20), background="pink")
    func1_lb3.place(x=220, y=160)
    func1_entry3 = tk.Entry(root_func1, width=45)
    func1_entry3.place(x=320, y=170)

    func1_lb4 = tk.Label(root_func1, text="选项B", font=("Helvetica", 20), background="pink")
    func1_lb4.place(x=220, y=200)
    func1_entry4 = tk.Entry(root_func1, width=45)
    func1_entry4.place(x=320, y=210)

    func1_lb5 = tk.Label(root_func1, text="选项C", font=("Helvetica", 20), background="pink")
    func1_lb5.place(x=220, y=240)
    func1_entry5 = tk.Entry(root_func1, width=45)
    func1_entry5.place(x=320, y=250)

    func1_lb6 = tk.Label(root_func1, text="选项D", font=("Helvetica", 20), background="pink")
    func1_lb6.place(x=220, y=280)
    func1_entry6 = tk.Entry(root_func1, width=45)
    func1_entry6.place(x=320, y=290)

    func1_lb7 = tk.Label(root_func1, text="正确答案", font=("Helvetica", 20), background="pink")
    func1_lb7.place(x=200, y=320)
    func1_entry7 = tk.Entry(root_func1, width=45)
    func1_entry7.place(x=320, y=330)

    func1_bt1 = tk.Button(root_func1, text="确定", font=("Helvetica", 20), background="pink",
                          command=lambda: func_ad_1_1(func1_entry1.get(), func1_entry2.get(), func1_entry3.get(),
                                                      func1_entry4.get(), func1_entry5.get(), func1_entry6.get(),
                                                      func1_entry7.get(), root_func1))
    func1_bt1.place(x=460, y=380)

    func1_bt2 = tk.Button(root_func1, text="取消", font=("Helvetica", 20), background="pink",
                          command=lambda: func_back(root_func1))
    func1_bt2.place(x=560, y=380)


def func_ad_1_1(x1, x2, x3, x4, x5, x6, x7, root_func1):  # 功能一的衍生函数
    root_func1.destroy()
    new_problem = SystemDesign.Problem(num=x1,
                                       question=x2,
                                       choice_a=x3,
                                       choice_b=x4,
                                       choice_c=x5,

                                       choice_d=x6,
                                       answer=x7)
    temp = {"题号": new_problem.num, "题目": new_problem.question, "选项A": new_problem.choice_a,
            "选项B": new_problem.choice_b, "选项C": new_problem.choice_c, "选项D": new_problem.choice_d,
            "正确答案": new_problem.answer}
    start.ProblemInfo.append(temp)
    start.save_information()
    message = tk.Tk()
    message.geometry("400x150")
    message.title("单项选择题答题与管理系统")
    message_lb = tk.Label(message, text="添加成功!", font=("等线", 30))
    message_lb.config(fg="red")
    message_lb.pack()
    message_bt = tk.Button(message, text="返回", height=1, width=8, command=lambda: func_back(message))
    message_bt.place(x=150, y=75)


def func_back(x):
    x.destroy()
    administrator_menu()


def func_ad_2(x):
    x.destroy()
    root_func2 = tk.Tk()
    root_func2.title("单项选择题答题与管理系统")
    root_func2.geometry("800x600")
    bt1 = tk.Button(root_func2, text="返回", width=600, font=("Helvetica", 20), command=lambda: func_back(root_func2))
    bt1.pack()
    frame_func2 = tk.Frame(root_func2)
    frame_func2.pack()
    scrollbar1 = tk.Scrollbar(frame_func2)
    scrollbar1.pack(side="right", fill="y")
    scrollbar2 = tk.Scrollbar(frame_func2, orient="horizontal")
    scrollbar2.pack(side="bottom", fill="x")
    list_func2 = tk.Listbox(frame_func2, selectmode='browse', width=500, height=20, font=("等线", 30),
                            xscrollcommand=scrollbar2.set, yscrollcommand=scrollbar1.set)
    for stu in start.StudentInfo:
        list_func2.insert("end", stu)
    list_func2.pack()
    scrollbar1.config(command=list_func2.yview)
    scrollbar2.config(command=list_func2.xview)


def func_ad_3(r):
    r.destroy()
    root_func3 = tk.Tk()
    root_func3.title("单项选择题答题与管理系统")
    root_func3.geometry("800x600")
    bt1 = tk.Button(root_func3, text="返回", width=600, font=("Helvetica", 20), command=lambda: func_back(root_func3))
    bt1.pack()
    frame_func3 = tk.Frame(root_func3)
    frame_func3.pack()
    scrollbar1 = tk.Scrollbar(frame_func3)
    scrollbar1.pack(side="right", fill="y")
    scrollbar2 = tk.Scrollbar(frame_func3, orient="horizontal")
    scrollbar2.pack(side="bottom", fill="x")
    list_func3 = tk.Listbox(frame_func3, selectmode='browse', width=500, height=20, font=("等线", 30),
                            xscrollcommand=scrollbar2.set, yscrollcommand=scrollbar1.set)
    tool = start.StudentInfo
    for del_zero in tool:
        if del_zero["成绩"] == "暂无成绩":
            del_zero["成绩"] = -1
    temp = sorted(tool, key=lambda x: int(x["成绩"]), reverse=True)
    list_stu = []
    for stu in temp:
        if stu["成绩"] == -1:
            stu["成绩"] = "暂无成绩"
        stu_pass = {"用户名": stu["用户名"],
                    "成绩": stu["成绩"],
                    "答题用时": stu["答题时间"]}
        list_stu.append(stu_pass)
    for stu in list_stu:
        list_func3.insert("end", stu)

    list_func3.pack()
    scrollbar1.config(command=list_func3.yview)
    scrollbar2.config(command=list_func3.xview)


def func_ad_4(x):
    x.destroy()
    root_func4 = tk.Tk()
    root_func4.title("单项选择题答题与管理系统")
    root_func4.geometry("800x600")
    bt1 = tk.Button(root_func4, text="返回", width=600, font=("Helvetica", 20), command=lambda: func_back(root_func4))
    bt1.pack()
    frame_func4 = tk.Frame(root_func4)
    frame_func4.pack()
    scrollbar1 = tk.Scrollbar(frame_func4)
    scrollbar1.pack(side="right", fill="y")
    scrollbar2 = tk.Scrollbar(frame_func4, orient="horizontal")
    scrollbar2.pack(side="bottom", fill="x")
    list_func2 = tk.Listbox(frame_func4, selectmode='browse', width=500, height=20, font=("等线", 30),
                            xscrollcommand=scrollbar2.set, yscrollcommand=scrollbar1.set)
    for stu in start.ProblemInfo:
        list_func2.insert("end", stu)
    list_func2.pack()
    scrollbar1.config(command=list_func2.yview)
    scrollbar2.config(command=list_func2.xview)


def func_ad_5(x):
    x.destroy()
    root_func5 = tk.Tk()
    root_func5.title("单项选择题答题与管理系统")
    root_func5.geometry("800x600")
    root_func5.config(background="pink")
    bt1 = tk.Button(root_func5, text="返回", width=600, font=("Helvetica", 20), command=lambda: func_back(root_func5))
    bt1.pack()
    lb1 = tk.Label(root_func5, background="pink", text="本次测试有%d道题目" % len(start.ProblemInfo),
                   font=("Helvetica", 40))
    lb1.pack()
    lb2 = tk.Label(root_func5, background="pink", text="满分%d分" % (len(start.ProblemInfo) * 5),
                   font=("Helvetica", 40))
    lb2.pack()
    student_num = 0
    total = 0
    for stu in start.StudentInfo:
        if stu["成绩"] == "暂无成绩":
            continue
        total += int(stu["成绩"])
        student_num += 1
    lb3 = tk.Label(root_func5, background="pink", text="参与测试%d人" % student_num, font=("Helvetica", 40))
    lb3.pack()
    lb3 = tk.Label(root_func5, background="pink", text="平均分:%0.2f" % (total / student_num), font=("Helvetica", 40))
    lb3.pack()


def func_ad_6(x):
    x.destroy()
    root_func6 = tk.Tk()
    root_func6.geometry("600x300")
    root_func6.title("单项选择题答题与管理系统")
    lb_func6 = tk.Label(root_func6, text="请输入要删除的试题题号!", font=("Helvetica", 20))
    lb_func6.pack()
    entry_func6 = tk.Entry(root_func6)
    entry_func6.place(x=220, y=60)
    bt1 = tk.Button(root_func6, height=1, width=8, text="确认",
                    command=lambda: func_ad_6_1(entry_func6.get()))
    bt1.place(x=220, y=100)
    bt2 = tk.Button(root_func6, height=1, width=8, text="取消", command=lambda: func_back(root_func6))
    bt2.place(x=300, y=100)


def func_ad_6_1(x):
    index = 0
    for pro in start.ProblemInfo:
        if pro["题号"] == x:
            del start.ProblemInfo[index]
            start.save_information()
            message = tk.Tk()
            message.geometry("400x150")
            message.title("单项选择题答题与管理系统")
            message_lb = tk.Label(message, text="删除成功!", font=("等线", 30))
            message_lb.config(fg="red")
            message_lb.pack()
            message_bt = tk.Button(message, text="返回", height=1, width=8, command=message.destroy)
            message_bt.place(x=150, y=75)
            return
        index += 1
    message = tk.Tk()
    message.geometry("400x150")
    message.title("单项选择题答题与管理系统")
    message_lb = tk.Label(message, text="未找到试题信息", font=("等线", 30))
    message_lb.config(fg="red")
    message_lb.pack()
    message_bt = tk.Button(message, text="返回", height=1, width=8, command=message.destroy)
    message_bt.place(x=150, y=75)


def func_ad_7(x):
    x.destroy()
    root_func7 = tk.Tk()
    root_func7.geometry("600x300")
    root_func7.title("单项选择题答题与管理系统")
    lb_func7 = tk.Label(root_func7, text="请输入要删除的学生账号!", font=("Helvetica", 20))
    lb_func7.pack()
    entry_func7 = tk.Entry(root_func7)
    entry_func7.place(x=220, y=60)
    bt1 = tk.Button(root_func7, height=1, width=8, text="确认",
                    command=lambda: func_ad_7_1(entry_func7.get()))
    bt1.place(x=220, y=100)
    bt2 = tk.Button(root_func7, height=1, width=8, text="取消", command=lambda: func_back(root_func7))
    bt2.place(x=300, y=100)


def func_ad_7_1(x):
    index = 0
    for pro in start.StudentInfo:
        if pro["账号"] == x:
            del start.StudentInfo[index]
            start.save_information()
            message = tk.Tk()
            message.geometry("400x150")
            message.title("单项选择题答题与管理系统")
            message_lb = tk.Label(message, text="删除成功!", font=("等线", 30))
            message_lb.config(fg="red")
            message_lb.pack()
            message_bt = tk.Button(message, text="返回", height=1, width=8, command=message.destroy)
            message_bt.place(x=150, y=75)
            return
        index += 1
    message = tk.Tk()
    message.geometry("400x150")
    message.title("单项选择题答题与管理系统")
    message_lb = tk.Label(message, text="未找到学生信息", font=("等线", 30))
    message_lb.config(fg="red")
    message_lb.pack()
    message_bt = tk.Button(message, text="返回", height=1, width=8, command=message.destroy)
    message_bt.place(x=150, y=75)


def func_ad_8(x):
    x.destroy()
    root.deiconify()


def student_menu(x):
    index = 0
    global grade
    grade = 0
    start_time = time.time()
    root.withdraw()
    root_stu = tk.Tk()
    root_stu.title("单项选择题答题与管理系统")
    root_stu.geometry("900x700")
    root_stu.config(background='pink')
    lb1 = tk.Label(root_stu, text="欢迎你%s同学" % x, font=("Helvetica", 40), background='pink')
    lb1.pack()
    bt1 = tk.Button(root_stu, text='1.开始答题', font=("Helvetica", 30), background='pink',
                    command=lambda: func_stu_1(root_stu, x, index, start_time))
    bt1.place(x=320, y=240)
    bt2 = tk.Button(root_stu, text='2.返回上级', font=("Helvetica", 30), background='pink',
                    command=lambda: func_stu_2(root_stu))
    bt2.place(x=320, y=360)


def func_stu_1(win, name, index_pro, start_time):
    win.destroy()
    root_func1 = tk.Tk()
    root_func1.title("单项选择题答题与管理系统")
    root_func1.geometry("900x700")
    root_func1.config(background='pink')
    func1title = tk.Label(root_func1, text="做下一题前请先提交当前题目!", font=("Helvetica", 40), background="pink")
    func1title.pack()

    temp = start.ProblemInfo[index_pro]

    pro_num = tk.Label(root_func1, text="%s." % temp["题号"], font=("Helvetica", 30), background="pink", )
    pro_num.place(x=200, y=80)

    pro_question = tk.Label(root_func1, text="%s" % temp["题目"], font=("Helvetica", 30), background="pink")
    pro_question.place(x=260, y=80)

    pro_a = tk.Label(root_func1, text="A.%s" % temp["选项A"], font=("Helvetica", 30), background="pink")
    pro_a.place(x=220, y=160)

    pro_b = tk.Label(root_func1, text="B.%s" % temp["选项B"], font=("Helvetica", 30), background="pink")
    pro_b.place(x=220, y=240)

    pro_c = tk.Label(root_func1, text="C.%s" % temp["选项C"], font=("Helvetica", 30), background="pink")
    pro_c.place(x=220, y=320)

    pro_d = tk.Label(root_func1, text="D.%s" % temp["选项D"], font=("Helvetica", 30), background="pink")
    pro_d.place(x=220, y=400)

    pro_answer = tk.Label(root_func1, text="你的选项为", font=("Helvetica", 30), background="pink")
    pro_answer.place(x=220, y=480)
    answer_get = tk.Entry(root_func1, font=("Helvetica", 30), width=2)
    answer_get.place(x=450, y=480)

    bt_ensure = tk.Button(root_func1, text="提 交", command=lambda: check_answer(answer_get.get(), temp["正确答案"]),
                          font=("Helvetica", 30), background="pink")
    bt_ensure.place(x=220, y=560)

    if index_pro == len(start.ProblemInfo) - 1:  # 目前只能下一题,且无法返回更改
        for stu in start.StudentInfo:
            if stu["用户名"] == name:
                stu["成绩"] = str(grade)
                stu["答题时间"] = str(int(time.time() - start_time))
                start.save_information()
        bt_end = tk.Button(root_func1, text="结束考试", command=lambda: func_stu_1_1(root_func1),
                           font=("Helvetica", 30), background="pink")
        bt_end.place(x=480, y=560)

    else:
        bt_down = tk.Button(root_func1, text="下一题",
                            command=lambda: func_stu_1(root_func1, name, index_pro + 1, start_time),
                            font=("Helvetica", 30),
                            background="pink")
        bt_down.place(x=480, y=560)


def check_answer(x, y):
    global grade
    if x == y:
        grade += 5


def func_stu_1_1(x):
    x.destroy()
    message = tk.Tk()
    message.geometry("400x150")
    message.title("单项选择题答题与管理系统")
    message_lb = tk.Label(message, text="答题结束!", font=("等线", 30))
    message_lb.config(fg="red")
    message_lb.pack()
    message_bt = tk.Button(message, text="返回", height=1, width=8, command=lambda: func_stu_2(message))
    message_bt.place(x=150, y=75)


def func_stu_1_2(x):
    x.destroy()
    root.deiconify()


def func_stu_2(x):
    x.destroy()
    root.deiconify()


def check_psw(x, y):
    if x == "123456":
        y.destroy()
        administrator_menu()
    else:
        message = tk.Tk()
        message.geometry("300x150")
        message.title("单项选择题答题与管理系统")
        message_lb = tk.Label(message, text="密码错误!", font=("等线", 30))
        message_lb.config(fg="red")
        message_lb.pack()
        message_bt = tk.Button(message, text="返回", height=1, width=8, command=message.destroy)
        message_bt.place(x=120, y=75)


def administrator_login():
    root3 = tk.Tk()
    root3.geometry("600x300")
    root3.title("单项选择题答题与管理系统")
    ad_login = tk.Label(root3, text="请输入管理员密码!", font=("Helvetica", 20))
    ad_login.pack()
    ad_login_entry = tk.Entry(root3, show="*")
    ad_login_entry.place(x=220, y=60)
    ad_login_bt1 = tk.Button(root3, height=1, width=8, text="确认",
                             command=lambda: check_psw(ad_login_entry.get(), root3))
    ad_login_bt1.place(x=220, y=100)
    ad_login_bt2 = tk.Button(root3, height=1, width=8, text="取消", command=root3.destroy)
    ad_login_bt2.place(x=300, y=100)


def student_login():
    root4 = tk.Tk()
    root4.geometry("600x300")
    root4.title("单项选择题答题与管理系统")
    st_login = tk.Label(root4, text="请输入账号和密码!", font=("Helvetica", 20))
    st_login.pack()
    st_lb1 = tk.Label(root4, text="账号", font=6)
    st_lb1.place(x=200, y=60)
    st_login_entry1 = tk.Entry(root4)
    st_login_entry1.place(x=250, y=60)
    st_lb2 = tk.Label(root4, text="密码", font=6)
    st_lb2.place(x=200, y=100)
    st_login_entry2 = tk.Entry(root4)
    st_login_entry2.place(x=250, y=100)
    st_login_bt1 = tk.Button(root4, height=1, width=8, text="确认",
                             command=lambda: student_check(st_login_entry1.get(), st_login_entry2.get(), root4))
    st_login_bt1.place(x=240, y=130)
    st_login_bt2 = tk.Button(root4, height=1, width=8, text="取消", command=root4.destroy)
    st_login_bt2.place(x=320, y=130)
    '''
    bt2 = tk.Button(root, text='1.开始答题', font=("Helvetica", 30), background='pink')
    bt2.place(x=300, y=180)
    bt3 = tk.Button(root, text='2.返回上级', font=("Helvetica", 30), background='pink')
    bt3.place(x=300, y=260)
    '''


def student_check(x, y, z):  # 检查学生的登录信息
    for stu in start.StudentInfo:
        if x == stu["账号"] and y == stu["密码"]:
            z.destroy()
            student_menu(stu["用户名"])
            break
    else:
        message = tk.Tk()
        message.geometry("400x150")
        message.title("单项选择题答题与管理系统")
        message_lb = tk.Label(message, text="账号或密码错误!", font=("等线", 30))
        message_lb.config(fg="red")
        message_lb.pack()
        message_bt = tk.Button(message, text="返回", height=1, width=8, command=message.destroy)
        message_bt.place(x=150, y=75)


def student_register():  # 注册学生信息页面
    root5 = tk.Tk()
    root5.geometry("600x300")
    root5.title("单项选择题答题与管理系统")
    st_login = tk.Label(root5, text="填写你的注册信息", font=("Helvetica", 20))
    st_login.pack()

    st_lb1 = tk.Label(root5, text="用户名", font=6)
    st_lb1.place(x=185, y=60)
    st_login_entry1 = tk.Entry(root5)
    st_login_entry1.place(x=250, y=60)

    st_lb2 = tk.Label(root5, text="账号", font=6)
    st_lb2.place(x=200, y=100)
    st_login_entry2 = tk.Entry(root5)
    st_login_entry2.place(x=250, y=100)

    st_lb2 = tk.Label(root5, text="密码", font=6)
    st_lb2.place(x=200, y=140)
    st_login_entry3 = tk.Entry(root5)
    st_login_entry3.place(x=250, y=140)

    st_login_bt1 = tk.Button(root5, height=1, width=8, text="确认",
                             command=lambda: add_student(st_login_entry1.get(), st_login_entry2.get(),
                                                         st_login_entry3.get(), root5))
    st_login_bt1.place(x=240, y=180)
    st_login_bt2 = tk.Button(root5, height=1, width=8, text="取消", command=root5.destroy)
    st_login_bt2.place(x=320, y=180)


def add_student(x, y, z, root5):  # 注册成功后的消息弹窗页面
    root5.destroy()
    new_student = SystemDesign.Student(name=x,
                                       user_name=y,
                                       user_password=z,
                                       grade="暂无成绩",
                                       usetime="暂无信息")
    temp = {"用户名": new_student.name, "账号": new_student.user_name, "密码": new_student.user_password,
            "成绩": new_student.grade, "答题时间": new_student.usetime}
    # 这里的new_student不能直接传入列表,要放在一个字典里把数据”打包“过去
    start.StudentInfo.append(temp)
    start.save_information()
    message = tk.Tk()
    message.geometry("400x150")
    message.title("单项选择题答题与管理系统")
    message_lb = tk.Label(message, text="添加成功!", font=("等线", 30))
    message_lb.config(fg="red")
    message_lb.pack()
    message_bt = tk.Button(message, text="返回", height=1, width=8, command=message.destroy)
    message_bt.place(x=150, y=75)


root = tk.Tk()
root.title("单项选择题答题与管理系统")
root.geometry("900x600")
root.config(background='pink')
main_label1 = tk.Label(root, text='单项选择题答题与管理系统', font=("Helvetica", 40), background='pink')
main_label1.pack()
main_bt1 = tk.Button(root, text='1.管理员登录', font=("Helvetica", 30), background='pink', command=administrator_login)
main_bt1.place(x=300, y=100)
main_bt2 = tk.Button(root, text='2.学生端登录', font=("Helvetica", 30), background='pink', command=student_login)
main_bt2.place(x=300, y=180)
main_bt3 = tk.Button(root, text='3. 注册学生账户', font=("Helvetica", 30), background='pink', command=student_register)
main_bt3.place(x=300, y=260)
main_bt4 = tk.Button(root, text='4.退出系统', font=("Helvetica", 30), background='pink', command=exit)
main_bt4.place(x=300, y=340)
global grade
root.mainloop()

若文章存在错误之处,欢迎指正!

你可能感兴趣的:(课程设计,python,开发语言,pycharm)