Python课程设计:Python语言实现自动组卷评卷考试系统

Python实现自动组卷评卷考试系统

  • 课程设计要求
  • 一、各个模块介绍及实现
    • 1. Configure.py
    • 2. File_Texture_Tree.py
    • 3. 后端:Test_Problem_Control.py
    • 4. 前端:Test_Window.py
  • 二、程序运行结果
    • 1.生成的文档结构图
    • 2.生成的答题GUI窗口
    • 附1:题库文档截图及文件夹的存放
    • 附2:一些文件的内容


课程设计要求

用Python语言编程实现自动组卷评卷考试系统,软件主要功能包括:
1. 从题库中随机抽取试题自动组成试卷(满分100分);
2. 实现考生考试答题操作界面;
3. 实现自动阅卷评分功能

要求:
(1)题型包括单项选择题、填空题、判断题等等。
(2)题库可以采用文本文件、CSV文件或数据库等来实现。
(3)要求在源程序中标注必要的注释。
(4)要求对程序的使用和运行方法进行必要说明。


一、各个模块介绍及实现

1. Configure.py

存储一些全局变量和函数。

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 22 12:34:46 2021

@author: stack
"""

import os

ResourcePath='\\'+'data'+'\\'

STATE_INIT = 1
STATE_SINGLE = 2
STATE_MULTI = 3
STATE_JUDGE = 4
STATE_DONE = 5

def getCurrentPath():
    path=os.getcwd() #当前工作路径
   # print(path)
    return path

def list2str(changList) -> str:
    res=''
    for i in range(len(changList)):
        res=res+str(changList[i])
    return res

2. File_Texture_Tree.py

产生文档结构树图,仅在windows环境下实现,未做linux扩展,如有需要,可以加if+os库判断平台进行修改。

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 22 17:16:37 2021

@author: stack
"""

from pathlib import Path
tree_str = ''

def generate_tree(pathname, n=0):
    global tree_str
    if pathname.is_file():
        tree_str += '    |' * n + '-' * 4 + pathname.name + '\n'
    elif pathname.is_dir():
        tree_str += '    |' * n + '-' * 4 + \
            str(pathname.relative_to(pathname.parent)) + '\\' + '\n'
        for cp in pathname.iterdir():
            generate_tree(cp, n + 1)


if __name__ == '__main__':
    generate_tree(Path.cwd())
    print(tree_str)

3. 后端:Test_Problem_Control.py

此为软件的后端,主要实现了以下几个功能:

1. 检测用户是否存在,并检查账号和密码是否正确
2. 添加新用户
3. 设置单选题的分值,并从题库中随机抽取10道单选题,返回数据至前端
4. 设置多选题的分值,并从题库中随机抽取10道多选题,返回数据至前端
5. 设置判断题的分值,并从题库中随机抽取10道判断题,返回数据至前端
6. 编写与前端的数据接口

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 22 15:38:33 2021

@author: stack
"""

import pandas as pd
import random 
from Configure import *

ResourcePath='\\'+'data'+'\\'

'''检测用户是否存在,并检查账号和密码是否正确'''
def checkAccount(filename) -> tuple:
    path = getCurrentPath() + ResourcePath + filename
    fid = open(path, 'r+')
    accountList = []
    userNameList, userPasswordList = [], []
    line = fid.readlines()
    for child in line:
        accountList.append(child.strip("\n").split('\t'))
    for name, password in accountList:
        userNameList.append(name)
        userPasswordList.append(password)
    fid.close()
    return userNameList, userPasswordList

'''添加新用户'''
def addUser(filename, userName:str, userPassword:str) -> int:
    path = getCurrentPath() + ResourcePath + filename
    txtfile = open(path, 'a')
    data = '\n' + userName + '\t' + userPassword
    txtfile.write(data)
    txtfile.close()
    return 1


'''单选题'''
class SingleChoiceSubject:
    def __init__(self):
        self.scorePer = 3  # 每道题的分值
        self.totalNum = 10  # 总共10道单选
        self.subjectList = {}  # 存放所有题目信息
        self.path = getCurrentPath() + ResourcePath + '原题集合.xlsx'
        self.df = pd.read_excel(self.path, sheet_name='单选题')
        self.tempList = []  # 存储一行信息
        self.randList = []  # 存储已经选用的题目,防止随机题目
        
    def generateRand(self):
        """ 产生随机题目序号 """
        count = 0
        while count < self.totalNum:
            randCount = random.randint(0, 19)  # 共20道单选题
            if randCount not in self.randList:
                self.randList.append(randCount)
                count = count + 1
            else:
                continue
    
    def getData(self):
        """ 获取题目,返回数据给前端 """
        self.generateRand()
        count = 0
        for randCount in self.randList:
            self.subjectList[count] = {}
            self.subjectList[count]['题目内容'] = self.df['题目内容'][randCount]
            self.subjectList[count]['A'] = self.df['A'][randCount]
            self.subjectList[count]['B'] = self.df['B'][randCount]
            self.subjectList[count]['C'] = self.df['C'][randCount]
            self.subjectList[count]['D'] = self.df['D'][randCount]
            self.subjectList[count]['E'] = self.df['E'][randCount]
            self.subjectList[count]['参考答案'] = self.df['参考答案'][randCount]
            count = count + 1
        return self.subjectList

'''多选题'''
class MultiChoiceSubject:
    def __init__(self):
        self.scorePer=5 #每道题五分
        self.totalNum=10  #Total problems are 10
        self.subjectList={}  #存放所有题目的信息
        self.path=getCurrentPath()+ResourcePath+'原题集合.xlsx'
        self.df=pd.read_excel(self.path,sheet_name='多选题')
        self.randList=[]
    
    def generateRand(self):
        """ 产生随机题目序号 """
        count = 0
        while count < self.totalNum:
            randCount = random.randint(0, 19)  # 共20道单选题
            if randCount not in self.randList:
                self.randList.append(randCount)
                count = count + 1
            else:
                continue
            
    def getData(self):
        """ 获取题目,返回数据给前端 """
        self.generateRand()
        count = 0
        for randCount in self.randList:
            self.subjectList[count] = {}
            self.subjectList[count]['题目内容'] = self.df['题目内容'][randCount]
            self.subjectList[count]['A'] = self.df['A'][randCount]
            self.subjectList[count]['B'] = self.df['B'][randCount]
            self.subjectList[count]['C'] = self.df['C'][randCount]
            self.subjectList[count]['D'] = self.df['D'][randCount]
            self.subjectList[count]['E'] = self.df['E'][randCount]
            self.subjectList[count]['参考答案'] = self.df['参考答案'][randCount]
            count = count + 1
        return self.subjectList
    

'''判断题'''
class JudgeSubject:
    def __init__(self):
        self.scorePer = 2  # 每道题的分值
        self.totalNum = 10  # 总共10道判断题
        self.subjectList = {}  # 存放所有题目信息
        self.path = getCurrentPath() + ResourcePath + '原题集合.xlsx'
        self.df = pd.read_excel(self.path, sheet_name='判断题')
        self.randList = []

    def generateRand(self):
        count = 0
        while count < self.totalNum:
            randCount = random.randint(0, 19)  # 共20道判断题
            if randCount not in self.randList:
                self.randList.append(randCount)
                count = count + 1
            else:
                continue

    def getData(self):
        self.generateRand()
        count = 0
        for randCount in self.randList:
            self.subjectList[count] = {}
            self.subjectList[count]['题目内容'] = self.df['题目内容'][randCount]
            self.subjectList[count]['参考答案'] = self.df['参考答案'][randCount]
            count = count + 1
        return self.subjectList


'''与前端的数据接口'''
class BackEnd:
    def __init__(self):
        self.Single = SingleChoiceSubject()
        self.Multi = MultiChoiceSubject()
        self.Judge = JudgeSubject()
        self.SingleList = self.Single.getData()
        self.MultiList = self.Multi.getData()
        self.JudgeList = self.Judge.getData()

    def test(self):
        print("SingleList:", self.SingleList)
        print("MultiList:", self.MultiList)
        print("JudgeList:", self.JudgeList)

4. 前端:Test_Window.py

前端是用来运行产生GUI答题界面的,是本次课程设计的主要代码。主要实现了以下功能:

  1. 对各种GUI界面如登录界面、答题界面等进行设置
  2. 对界面上的各种功能进行设置
  3. 接受后端的数据
  4. 登录/注册,输入账号和密码进入答题界面
  5. 将随机选中的问题显示在GUI界面上,并选择相应的选项完成问题
  6. 答题完成,根据分数出现相应的图片
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 22 12:02:24 2021

@author: stack
"""

import tkinter as tk
from tkinter import messagebox
from tkinter import scrolledtext
from threading import Timer
from Configure import *
from PIL import Image, ImageTk
from Test_Problem_Control import BackEnd, checkAccount, addUser

ResourcePath='\\'+'data'+'\\'

dataList=BackEnd()  #存储得到的考题

im=[] #读取文件
img=[] #转换格式后

for i in range(5):
    im.append(None)
    img.append(None)

'''前端类,完成注册和答题两个界面和数据调用'''
class FrontEnd:
    def __init__(self):
        self.state = STATE_INIT  # 完成题目衔接和变化
        self.count = 0  # 计数题号
        self.minute = 20 #设置答题时间为20min
        self.second = 0  # 设定答题时间20min
        self.ans = []  # 存放考生的结果,确认后判断
        self.score = 0  # 计算得到的分数
        self.loginWindow = tk.Tk()
        self.initialLoginWindow(self.loginWindow)
        
    '''初始化窗口'''
    def initialLoginWindow(self, loginWindow):
        loginWindow['bg'] = '#999999'  # 登录界面的背景颜色为灰色
        loginWindow.title('Login in Window By 2018080901018')
        loginWindow.resizable(width=True, height=True)

        width = loginWindow.winfo_screenwidth()
        height = loginWindow.winfo_screenheight()
        loginWindow.geometry(
            "400x200+%d+%d" %
            (width / 2 - 200, height / 2 - 200))

        self.varAccount = tk.StringVar()
        self.varAccount.set('')
        self.varKey = tk.StringVar()
        self.varKey.set('')

        # 创建标签
        self.labelAccount = tk.Label(
            loginWindow,
            text='User Name',
            justify=tk.RIGHT,
            font=('Arial', 14),
            width=80)
        self.labelKey = tk.Label(
            loginWindow,
            text='Password',
            font=('Arial', 14),
            justify=tk.RIGHT,
            width=80)
        self.labelRegister = tk.Label(
            loginWindow, text='Register', justify=tk.RIGHT, width=80)

        #为窗口的标签设置属性
        self.labelAccount.place(x=20, y=10, width=160, height=40)
        self.labelKey.place(x=20, y=60, width=160, height=40)

        # 创建账号文本框,同时设置关联的变量
        self.account = tk.Entry(
            loginWindow,
            width=80,
            textvariable=self.varAccount)
        self.account.place(x=200, y=10, width=160, height=40)
        #self.account=tk.Label(font=('Arial',12),justify='center')
        
        # 创建密码文本框
        self.key = tk.Entry(
            loginWindow,
            show='*',
            width=80,
            textvariable=self.varKey)
        self.key.place(x=200, y=60, width=160, height=40)

        # 创建按钮组件,同时设置按钮事件处理函数
        buttonOk = tk.Button(loginWindow, text='Login', command=self.login)
#        buttonOK=tk.Label(font=('Arial', 14))
        buttonOk.place(x=20, y=140, width=100, height=40)
        buttonRegister = tk.Button(loginWindow, text='Register', command=self.regist)
        buttonRegister.place(x=260, y=140, width=100, height=40)

        # make Esc exit the program
        loginWindow.bind('', lambda e: loginWindow.destroy())
        # 启动消息循环
        loginWindow.mainloop()

    def login(self):
        """ 获取用户名和密码 """
        name = self.account.get()
        passwd = self.key.get()

        nameList, passwordList = checkAccount('Account.txt')
        # for test
        for i in range(len(nameList)):
            if name == nameList[i]:
                if passwd == passwordList[i]:
                    tk.messagebox.showinfo(title='TEST GUI', message='Login in Successfully!')
                    self.loginWindow.destroy()
                    self.mainWindow = tk.Tk()
                    self.initialMainWindow(self.mainWindow)
                    return
        tk.messagebox.showerror('TEST GUI', message='Your name or code could be wrong!')

    #def cancelLogin(self):
        """ 清空用户输入的用户名和密码 """
      #  self.varAccount.set('')
     #   self.varKey.set('')

    def regist(self):
        name = self.account.get()
        passwd = self.key.get()
        userNameList, userPasswordList = checkAccount('Account.txt')
        if not userNameList or not userPasswordList:
            addUser('Account.txt', name, passwd)
            return
        for userName in userNameList:
            if name == userName:
                tk.messagebox.showerror('TSET GUI', message='Name Already Exists!')
        registerSuccessful = addUser('Account.txt', name, passwd)
        if registerSuccessful:
            messagebox.showinfo('Hint Information', message='Register Successfully!')

    def initialMainWindow(self, mainWindow):
        '''初始化窗口和窗口设置'''
        self.width = mainWindow.winfo_screenwidth()
        self.height = mainWindow.winfo_screenheight()

        print('[Function: initialMainWindow]')
        mainWindow.geometry("%dx%d" % (self.width, self.height))
        mainWindow['bg'] = '#E4E5B5'  # background color
        mainWindow.title('Test Window By 2018080901018')
        mainWindow.resizable(width=True, height=True)

        mainWindow.protocol('WM_DELETE_WINDOW', self.closeMainWindow)
        self.setMenu(mainWindow)
        # make Esc exit the program
        mainWindow.bind('', lambda e: mainWindow.destroy())

        self.totalCount = dataList.Single.totalNum + \
                          dataList.Multi.totalNum + dataList.Judge.totalNum

        self.showInitFsm()
        self.watchDog()
        mainWindow.mainloop()

    def showInitFsm(self):
        nextState = STATE_SINGLE
        print('[Function: Init_fsm] startup')

        self.varScore = tk.StringVar()  # 已获得分数
        self.varScore.set(str(self.score) + '\100')
        self.showScoreName = tk.Label(self.mainWindow,
                                      text='SCORES',
                                      justify='center',  # 设置文本对齐方式:居中对齐
                                      anchor='center',  # 设置文本在label的方位:居中对齐
                                      font=('Berlin Sans FB Demi Bold', 18),  
                                      # 设置字体:Berlin Sans FB Demi Bold,字号:18
                                      fg='#04213A',  # 设置前景色:黑色
                                      bg='#D2EBFF',  # 设置背景色:天蓝色
                                      )
        self.showScoreName.place(x=10, y=10, width=150, height=50)
        self.showScore = tk.Label(self.mainWindow, textvariable=self.varScore)
        self.showScore.place(x=10, y=70, width=150, height=50)
        self.varTimeLft = tk.StringVar()
        self.timeLeft = tk.Label(self.mainWindow, textvariable=self.varTimeLft)
        self.timeLeft.place(x=self.width - 200, y=70, width=150, height=50)

        self.showTimeLeft = tk.Label(self.mainWindow, text='Time Left',  # 设置文本内容
                                     justify='center',  # 设置文本对齐方式:居中对齐
                                     anchor='center',  # 设置文本在label的方位:居中对齐
                                     font=('Arial', 18),  # 设置字体:Arial,字号:18
                                     fg='white',  # 设置前景色:白色
                                     bg='grey',  # 设置背景色:灰色
                                     padx=20,  # 设置x方向内边距:20
                                     pady=10)  # 设置y方向内边距:10
        self.showTimeLeft.place(x=self.width - 200, y=10, width=150, height=60)

        self.varButtonA = tk.StringVar()
        self.varButtonA.set(
            'A. ' + str(dataList.SingleList[self.count % 10]['A']))
        self.varButtonB = tk.StringVar()
        self.varButtonB.set(
            'B. ' + str(dataList.SingleList[self.count % 10]['B']))
        self.varButtonC = tk.StringVar()
        self.varButtonC.set(
            'C. ' + str(dataList.SingleList[self.count % 10]['C']))
        self.varButtonD = tk.StringVar()
        self.varButtonD.set(
            'D. ' + str(dataList.SingleList[self.count % 10]['D']))
        self.varButtonE = tk.StringVar()
        self.varButtonE.set('')

        self.buttonA = tk.Button(self.mainWindow,
                                 textvariable=self.varButtonA,
                                 command=self.buttonAFsm)
        self.buttonB = tk.Button(self.mainWindow,
                                 textvariable=self.varButtonB,
                                 command=self.buttonBFsm)
        self.buttonC = tk.Button(self.mainWindow,
                                 textvariable=self.varButtonC,
                                 command=self.buttonCFsm)
        self.buttonD = tk.Button(self.mainWindow,
                                 textvariable=self.varButtonD,
                                 command=self.buttonDFsm)
        self.buttonOK = tk.Button(self.mainWindow,
                                  text='OK',
                                  command=self.buttonOKFsm)  # 确认按钮,确认不再更改答案
        self.buttonA.place(x=100, y=400, width=750, height=50)
        self.buttonB.place(x=100, y=460, width=750, height=50)
        self.buttonC.place(x=100, y=520, width=750, height=50)
        self.buttonD.place(x=100, y=580, width=750, height=50)
        self.buttonOK.place(x=1000, y=490, width=300, height=50)

        self.varChoice = tk.StringVar()
        self.varChoice.set(list2str(self.ans))  # 显示已经选择的选项
        self.showChoice = tk.Label(
            self.mainWindow, textvariable=self.varChoice)
        self.showChoice.place(x=1100, y=550, width=100, height=50)
        self.subject = scrolledtext.ScrolledText(
            self.mainWindow, relief="solid")
        self.subject.place(x=self.width / 3, y=10)
        self.subject.insert('end', str(self.count + 1) + '. ' +
                            dataList.SingleList[self.count]['题目内容'] + '\n')

        self.count = 0
        print('[Function: Init_fsm] complicated')
        self.state = nextState

    def buttonAFsm(self):
        print('     [Event: buttonA clicked]')
        if self.state == STATE_SINGLE:  # 单选
            self.ans = []
            self.ans.append('A')
        elif self.state == STATE_MULTI:  # 多选
            if 'A' not in self.ans:
                self.ans.append('A')
                self.ans = sorted(self.ans)
            else:
                self.ans.remove('A')
        else:  # 判断题
            self.ans = []
            self.ans.append('√')
        self.varChoice.set(list2str(self.ans))

    def buttonBFsm(self):
        print('     [Event: buttonB clicked]')
        if self.state == STATE_SINGLE:  # 单选
            self.ans = []
            self.ans.append('B')
        elif self.state == STATE_MULTI:  # 多选
            if 'B' not in self.ans:
                self.ans.append('B')
                self.ans = sorted(self.ans)
            else:
                self.ans.remove('B')
                sorted(self.ans)
        else:
            self.ans = []
            self.ans.append('√')
        self.varChoice.set(list2str(self.ans))

    def buttonCFsm(self):
        print('     [Event: buttonC clicked]')
        if self.state == STATE_SINGLE:  # 单选
            self.ans = []
            self.ans.append('C')
        elif self.state == STATE_MULTI:  # 多选
            if 'C' not in self.ans:
                self.ans.append('C')
                self.ans = sorted(self.ans)
            else:
                self.ans.remove('C')
                sorted(self.ans)
        else:  # 判断
            self.ans = []
            self.ans.append('×')
        self.varChoice.set(list2str(self.ans))

    def buttonDFsm(self):
        print('     [Event: buttonD clicked]')
        if self.state == STATE_SINGLE:  # 单选
            self.ans = []
            self.ans.append('D')
        elif self.state == STATE_MULTI:  # 多选
            if 'D' not in self.ans:
                self.ans.append('D')
                self.ans = sorted(self.ans)
            else:
                self.ans.remove('D')
                sorted(self.ans)
        else:  # 判断
            self.ans = []
            self.ans.append('×')
        self.varChoice.set(list2str(self.ans))

    def buttonEFsm(self):
        print('     [Event: buttonE clicked]')
        if self.state == STATE_SINGLE:  # 单选
            self.ans = []
            self.ans.append('E')
        elif self.state == STATE_MULTI:  # 多选
            if 'E' not in self.ans:
                self.ans.append('E')
                self.ans = sorted(self.ans)
            else:
                self.ans.remove('E')
                sorted(self.ans)
        else:  # 判断
            self.ans = []
            self.ans.append('×')
        self.varChoice.set(list2str(self.ans))

    def buttonOKFsm(self):
        """进入下一状态 """
        print('     [Event: buttonOK clicked]')
        
        self.score += self.checkAns()
        self.varScore.set(str(self.score) + '/100')  # 显示得分

        self.count = self.count + 1  # 题号加一
        self.varChoice.set('')  # 清空显示的选项

        self.ans = []  # 清空内部存储的选项
        if self.state == STATE_SINGLE:
            self.showSingleFsm()
        elif self.state == STATE_MULTI:
            self.showMultiFsm()
        elif self.state == STATE_JUDGE:
            self.showJudgeFsm()
        else:  # 分数不再变动
            self.showDoneFsm()

    def checkAns(self) -> int:
        """ 检查结果,返回本题得分 """
        if self.state == STATE_SINGLE:
            print('     [Debug: your choice:] ' + str(self.ans))
            if list2str(
                    self.ans) == dataList.SingleList[self.count % 10]['参考答案']:
                return 3
            else:
                return 0
        elif self.state == STATE_MULTI:
            print('     [Debug: your choice:] ' + str(self.ans))
            if list2str(
                    self.ans) == dataList.MultiList[self.count % 10]['参考答案']:
                return 5
            else:
                return 0
        else:
            print('     [Debug: your choice:] ' + str(self.ans))
            if list2str(
                    self.ans) == dataList.JudgeList[self.count % 10]['参考答案']:
                return 2
            else:
                return 0

    def updateSubject(self, listName):
        self.subject.delete(0.0, tk.END)
        self.subject.insert('end', str(self.count + 1) + '. ' +
                            listName[self.count % 10]['题目内容'] + '\n')
        self.varButtonA.set(
            'A. ' + str(listName[self.count % 10]['A']))
        self.varButtonB.set(
            'B. ' + str(listName[self.count % 10]['B']))
        self.varButtonC.set(
            'C. ' + str(listName[self.count % 10]['C']))
        self.varButtonD.set(
            'D. ' + str(listName[self.count % 10]['D']))
        if self.state == STATE_MULTI:
            self.varButtonE.set(
                'E. ' + str(listName[self.count % 10]['E']))

    def showSingleFsm(self):
        if self.count < self.totalCount / 3 - 1:
            nextState = STATE_SINGLE
        else:
            nextState = STATE_MULTI
            self.buttonE = tk.Button(self.mainWindow,
                                     textvariable=self.varButtonE,
                                     command=self.buttonEFsm)
            self.buttonA.place(x=100, y=400, width=750, height=50)
            self.buttonB.place(x=100, y=480, width=750, height=50)
            self.buttonC.place(x=100, y=560, width=750, height=50)
            self.buttonD.place(x=100, y=640, width=750, height=50)
            self.buttonE.place(x=100, y=720, width=750, height=50)

        self.updateSubject(dataList.SingleList)

        self.state = nextState

    def showMultiFsm(self):
        if self.totalCount / 3 <= self.count < 2 * self.totalCount / 3:
            nextState = STATE_MULTI
        else:
            nextState = STATE_JUDGE
            self.buttonA.destroy()
            self.buttonB.destroy()
            self.buttonC.destroy()
            self.buttonD.destroy()
            self.buttonE.destroy()
            self.buttonTrue = tk.Button(self.mainWindow,
                                        text='√',
                                        command=self.buttonAFsm)
            self.buttonFalse = tk.Button(self.mainWindow,
                                         text='×',
                                         command=self.buttonEFsm)
            self.buttonTrue.place(x=100, y=400, width=750, height=50)
            self.buttonFalse.place(x=100, y=500, width=750, height=50)

        self.updateSubject(dataList.MultiList)  # 刷新题目和选项

        self.state = nextState

    def showJudgeFsm(self):
        print('total count: ', self.totalCount)
        if self.count < self.totalCount:
            nextState = STATE_JUDGE
        else:
            nextState = STATE_DONE

        self.subject.delete(0.0, tk.END)  # 清空上一题
        self.subject.insert('end', str(self.count + 1) + '. ' +
                            dataList.JudgeList[self.count % 10]['题目内容'] + '\n')

        self.state = nextState

    def showDoneFsm(self):
        """ 结束状态 """

        # 清除所有无用控件
        self.buttonTrue.destroy()
        self.buttonFalse.destroy()
        self.buttonOK.destroy()
        self.showChoice.destroy()
        self.subject.destroy()

        # 计时结束
        self.timeCount.cancel()

        self.showScoreName = tk.Label(self.mainWindow,
                                      text='Total Scores',
                                      justify='center',  # 设置文本对齐方式:左对齐
                                      anchor='center',  # 设置文本在label的方位:西北方位
                                      font=('Berlin Sans FB Demi Bold', 18), 
                                      # 设置字体:Berlin Sans FB Demi Bold,字号:18
                                      fg='white',  # 设置前景色:白色
                                      bg='grey',  # 设置背景色:灰色
                                      )
        self.showScoreName.place(x=10, y=10, width=150, height=50)

        # 加载图像
        global im
        global img

        if self.score < 60:
            im[0] = Image.open(getCurrentPath() + ResourcePath + "pic1.jpg")
            img[0] = ImageTk.PhotoImage(im[0])
            imLabel = tk.Label(self.mainWindow, image=img[0]).pack()
        elif 60 <= self.score <= 70:
            im[1] = Image.open(getCurrentPath() + ResourcePath + "pic2.jpg")
            img[1] = ImageTk.PhotoImage(im[1])
            imLabel = tk.Label(self.mainWindow, image=img[1]).pack()
        elif 70 <= self.score <= 85:
            im[2] = Image.open(getCurrentPath() + ResourcePath + "pic3.jpg")
            img[2] = ImageTk.PhotoImage(im[2])
            imLabel = tk.Label(self.mainWindow, image=img[2]).pack()
        elif 85 <= self.score <= 100:
            im[3] = Image.open(getCurrentPath() + ResourcePath + "pic4.jpg")
            img[3] = ImageTk.PhotoImage(im[3])
            imLabel = tk.Label(self.mainWindow, image=img[3]).pack()
        else:
            pass

    def setMenu(self, window):
        """定义一个菜单栏,方便离开,并显示开发者信息"""
        menubar = tk.Menu(window)
        filemenu = tk.Menu(menubar, tearoff=0)
        filemenu.add_command(label="Exit", command=window.destroy)
        infoMenu = tk.Menu(menubar, tearoff=0)
        infoMenu.add_command(
            label="Version Info",
            command=self.menuInfo
        )
        menubar.add_cascade(label="File", menu=filemenu)
        menubar.add_cascade(label="Info", menu=infoMenu)
        window.config(menu=menubar)

    def menuInfo(self):#显示开发者信息
        messagebox.showinfo(
            'Information',
            'Created By Jason Stackhouze, 2018080901018, 2020-01-16')
 
    def watchDog(self):
        """ 定时程序,时间最多一小时"""
        timeLeft = 60 * self.minute + self.second

        timeLeft -= 1
        self.second = self.second - 1
        if self.second < 0:
            self.minute = self.minute - 1
            self.second = 59
        if self.minute < 0 or timeLeft == 0:
            self.state = STATE_DONE
            self.showDoneFsm()
        self.varTimeLft.set(str(self.minute) + ':' + str(self.second))
        self.timeCount = Timer(1, self.watchDog, ())
        self.timeCount.start() # 计时器启动

    def closeMainWindow(self):
        '''确认是否退出程序'''
        ans = messagebox.askyesno(title='Exit', message='Do you really want to exit?')
        if ans:
            self.mainWindow.destroy()
        else:
            pass


if __name__ == '__main__':
    test = FrontEnd()

二、程序运行结果

1.生成的文档结构图

如下:

----课程设计\
    |----build\
    |    |----guess_exe\
    |    |----Test_Window\
    |    |    |----base_library.zip
    |    |    |----Test_Window.exe.manifest
    |----Configure.py
    |----data\
    |    |----Account.txt
    |    |----pic1.jpg
    |    |----pic2.jpg
    |    |----pic3.jpg
    |    |----pic4.jpg
    |    |----原题集合.xlsx
    |----dist\
    |----File_Texture_Tree.py
    |----Test_Problem_Control.py
    |----Test_Window.py
    |----Test_Window.spec
    |----__pycache__\
    |    |----Configure.cpython-37.pyc
    |    |----Test_Problem_Control.cpython-37.pyc
    |----~$&运行方法简要说明.docx
    |----使用&运行方法简要说明.docx
    |----使用&运行方法简要说明.pdf
    |----说明.txt


***Repl Closed***

2.生成的答题GUI窗口

出现如下所示的登录界面:
Python课程设计:Python语言实现自动组卷评卷考试系统_第1张图片

登录后,出现答题界面:
Python课程设计:Python语言实现自动组卷评卷考试系统_第2张图片
继续回答问题,直至完成所有问题。如果不慎点中右上角的“×”,则会询问你是否真的要退出。
Python课程设计:Python语言实现自动组卷评卷考试系统_第3张图片
答完所有题后,按照代码中的设置,根据你所得分数显示相应图片:

100分:
Python课程设计:Python语言实现自动组卷评卷考试系统_第4张图片
6分:
Python课程设计:Python语言实现自动组卷评卷考试系统_第5张图片

 if self.score < 60:
            im[0] = Image.open(getCurrentPath() + ResourcePath + "pic1.jpg")
            img[0] = ImageTk.PhotoImage(im[0])
            imLabel = tk.Label(self.mainWindow, image=img[0]).pack()
        elif 60 <= self.score <= 70:
            im[1] = Image.open(getCurrentPath() + ResourcePath + "pic2.jpg")
            img[1] = ImageTk.PhotoImage(im[1])
            imLabel = tk.Label(self.mainWindow, image=img[1]).pack()
        elif 70 <= self.score <= 85:
            im[2] = Image.open(getCurrentPath() + ResourcePath + "pic3.jpg")
            img[2] = ImageTk.PhotoImage(im[2])
            imLabel = tk.Label(self.mainWindow, image=img[2]).pack()
        elif 85 <= self.score <= 100:
            im[3] = Image.open(getCurrentPath() + ResourcePath + "pic4.jpg")
            img[3] = ImageTk.PhotoImage(im[3])
            imLabel = tk.Label(self.mainWindow, image=img[3]).pack()
        else:
            pass

点击“File”的“Exit”或者右上角的“×”,退出系统
Python课程设计:Python语言实现自动组卷评卷考试系统_第6张图片

附1:题库文档截图及文件夹的存放

写入一个Excel文件即可
Python课程设计:Python语言实现自动组卷评卷考试系统_第7张图片
Python课程设计:Python语言实现自动组卷评卷考试系统_第8张图片
Python课程设计:Python语言实现自动组卷评卷考试系统_第9张图片
将这些文件放置在一个文件夹中:
Python课程设计:Python语言实现自动组卷评卷考试系统_第10张图片
另外,data文件夹中的文件如图所示:
Python课程设计:Python语言实现自动组卷评卷考试系统_第11张图片


附2:一些文件的内容

Account:(话说这不是输入后自动保存吗,我不太记得了……)
Python课程设计:Python语言实现自动组卷评卷考试系统_第12张图片

另外,dist和build文件夹不需要自己建立,这是自动生成的

你可能感兴趣的:(python,gui)