多项选择测验或考试生成器



我正在尝试创建一个脚本或应用程序来创建多项选择测验。它将允许用户输入一个问题,然后给出一个真实的答案和一些可供选择的答案。用户可以根据需要多次重复该过程。然后,用户需要输入创建的测验将具有的问题数。最后,测验将被保存为pdf或word文档。所有这些都需要Qt制造的GUI。到目前为止,我已经制作了大部分测验脚本,并且它工作正常。(仍然需要弄清楚如何在答案前面添加a,b,c...并保存到pdf,但这不是问题(。gui 也完成了,我认为它应该正常工作。

问题是我不知道如何将测验脚本与 gui 连接起来。我尝试了很多东西,但没有一个奏效。

import json
import random
def quiz_name():
name = input('Enter the name of the quiz file: ')
return name
def question_generator():
question_text = input('Enter a question. When done entering questions type 'stop': ')
if question_text.lower() == 'stop':
return None
true = input('Enter the correct answer: ')
answer_dict = []
while True:
answer = input('Enter an answer. When done entering questions type 'stop': ')
if answer.lower() == 'stop':
break
answer_dict.append(answer)         
qapair = (question_text, true, answer_dict) 
return qapair

def question_list_builder():
questions = []
while True:
qg_method = question_generator()
if qg_method is None:
break
q = (qg_method[0], qg_method[1],qg_method[2]) 
questions.append(q)
return questions
#lista_pitanja = question_list_builder()
#for lp in lista_pitanja:
#    pitanje=lista_pitanja
#    broj =0
#    while broj <len(lista_pitanja[2]):
#        print(broj+1,+': '+)
#        broj+=1
class ObjectEncoder(json.JSONEncoder):
def default(self, obj):
return obj.__dict__
if __name__ == '__main__':
quest = question_list_builder()
name = quiz_name()
def JSONWrite(quiz, filepath):
with open(f'{filepath}.json', 'w') as fp:
fp.write(quiz)
print(json.dumps(quest, cls=ObjectEncoder))
#    random.sample(pitanja,4)
JSONWrite(json.dumps(random.sample(quest,3), cls=ObjectEncoder, indent=4),name)

如果需要,我将粘贴 gui 代码

编辑:添加了 gui 代码

from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(1077, 943)
self.gridLayout = QtWidgets.QGridLayout(Form)
self.gridLayout.setObjectName("gridLayout")
self.line_3 = QtWidgets.QFrame(Form)
self.line_3.setFrameShape(QtWidgets.QFrame.VLine)
self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_3.setObjectName("line_3")
self.gridLayout.addWidget(self.line_3, 0, 4, 1, 1)
self.line_4 = QtWidgets.QFrame(Form)
self.line_4.setFrameShape(QtWidgets.QFrame.VLine)
self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_4.setObjectName("line_4")
self.gridLayout.addWidget(self.line_4, 0, 0, 1, 1)
self.gridLayout_2 = QtWidgets.QGridLayout()
self.gridLayout_2.setObjectName("gridLayout_2")
self.Answer_btn = QtWidgets.QPushButton(Form)
self.Answer_btn.setObjectName("Answer_btn")
self.gridLayout_2.addWidget(self.Answer_btn, 4, 2, 1, 1)
self.LE_datName = QtWidgets.QLineEdit(Form)
self.LE_datName.setObjectName("LE_datName")
self.gridLayout_2.addWidget(self.LE_datName, 7, 1, 1, 1)
self.label_datName = QtWidgets.QLabel(Form)
self.label_datName.setObjectName("label_datName")
self.gridLayout_2.addWidget(self.label_datName, 7, 0, 1, 1)
self.Question_btn = QtWidgets.QPushButton(Form)
self.Question_btn.setObjectName("Question_btn")
self.gridLayout_2.addWidget(self.Question_btn, 1, 2, 1, 1)
self.LE_TAnswer = QtWidgets.QLineEdit(Form)
self.LE_TAnswer.setObjectName("LE_TAnswer")
self.gridLayout_2.addWidget(self.LE_TAnswer, 3, 1, 1, 1)
self.LE_Answer = QtWidgets.QLineEdit(Form)
self.LE_Answer.setObjectName("LE_Answer")
self.gridLayout_2.addWidget(self.LE_Answer, 4, 1, 1, 1)
self.line_2 = QtWidgets.QFrame(Form)
self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_2.setObjectName("line_2")
self.gridLayout_2.addWidget(self.line_2, 8, 0, 1, 4)
self.label_NQuestion = QtWidgets.QLabel(Form)
self.label_NQuestion.setObjectName("label_NQuestion")
self.gridLayout_2.addWidget(self.label_NQuestion, 9, 0, 1, 1)
self.label_Answer = QtWidgets.QLabel(Form)
self.label_Answer.setFrameShape(QtWidgets.QFrame.NoFrame)
self.label_Answer.setTextFormat(QtCore.Qt.AutoText)
self.label_Answer.setScaledContents(False)
self.label_Answer.setObjectName("label_Answer")
self.gridLayout_2.addWidget(self.label_Answer, 4, 0, 1, 1)
self.LE_NQuestions = QtWidgets.QLineEdit(Form)
self.LE_NQuestions.setObjectName("LE_NQuestions")
self.gridLayout_2.addWidget(self.LE_NQuestions, 9, 1, 1, 1)
self.New_Question_btn = QtWidgets.QPushButton(Form)
self.New_Question_btn.setObjectName("New_Question_btn")
self.gridLayout_2.addWidget(self.New_Question_btn, 4, 3, 1, 1)
self.TAnswer_btn = QtWidgets.QPushButton(Form)
self.TAnswer_btn.setObjectName("TAnswer_btn")
self.gridLayout_2.addWidget(self.TAnswer_btn, 3, 2, 1, 1)
self.line = QtWidgets.QFrame(Form)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.gridLayout_2.addWidget(self.line, 6, 0, 1, 4)
self.Dat_btn = QtWidgets.QPushButton(Form)
self.Dat_btn.setObjectName("Dat_btn")
self.gridLayout_2.addWidget(self.Dat_btn, 7, 2, 1, 1)
self.label_TAnswer = QtWidgets.QLabel(Form)
self.label_TAnswer.setObjectName("label_TAnswer")
self.gridLayout_2.addWidget(self.label_TAnswer, 3, 0, 1, 1)
self.Generate_btn = QtWidgets.QPushButton(Form)
self.Generate_btn.setObjectName("Generate_btn")
self.gridLayout_2.addWidget(self.Generate_btn, 9, 3, 1, 1)
self.NQuestion_btn = QtWidgets.QPushButton(Form)
self.NQuestion_btn.setObjectName("NQuestion_btn")
self.gridLayout_2.addWidget(self.NQuestion_btn, 9, 2, 1, 1)
self.LE_Question = QtWidgets.QLineEdit(Form)
self.LE_Question.setToolTipDuration(-1)
self.LE_Question.setText("")
self.LE_Question.setObjectName("LE_Question")
self.gridLayout_2.addWidget(self.LE_Question, 1, 1, 1, 1)
self.Done_btn = QtWidgets.QPushButton(Form)
self.Done_btn.setObjectName("Done_btn")
self.gridLayout_2.addWidget(self.Done_btn, 5, 2, 1, 1)
self.line_okv2 = QtWidgets.QFrame(Form)
self.line_okv2.setLineWidth(5)
self.line_okv2.setFrameShape(QtWidgets.QFrame.HLine)
self.line_okv2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_okv2.setObjectName("line_okv2")
self.gridLayout_2.addWidget(self.line_okv2, 10, 0, 1, 4)
self.line_okv1 = QtWidgets.QFrame(Form)
self.line_okv1.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_okv1.setLineWidth(3)
self.line_okv1.setFrameShape(QtWidgets.QFrame.HLine)
self.line_okv1.setObjectName("line_okv1")
self.gridLayout_2.addWidget(self.line_okv1, 0, 0, 1, 4)
self.label_Question = QtWidgets.QLabel(Form)
self.label_Question.setObjectName("label_Question")
self.gridLayout_2.addWidget(self.label_Question, 1, 0, 1, 1)
self.gridLayout.addLayout(self.gridLayout_2, 0, 1, 1, 1)
self.retranslateUi(Form)
self.Answer_btn.pressed.connect(self.LE_Answer.clear)
self.New_Question_btn.clicked.connect(self.LE_Question.clear)
self.New_Question_btn.clicked.connect(self.LE_TAnswer.clear)
self.New_Question_btn.clicked.connect(self.LE_Answer.clear)
self.Generate_btn.clicked.connect(self.LE_NQuestions.clear)
self.Generate_btn.clicked.connect(self.LE_datName.clear)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Kolokvij"))
self.Answer_btn.setText(_translate("Form", "Enter Answer"))
self.label_datName.setText(_translate("Form", "Enter the name of the file:"))
self.Question_btn.setToolTip(_translate("Form", "Pritisnite ovo"))
self.Question_btn.setText(_translate("Form", "Enter Question"))
self.label_NQuestion.setText(_translate("Form", "Number of questions in exam:"))
self.label_Answer.setText(_translate("Form", "Enter all the possible answers:"))
self.New_Question_btn.setText(_translate("Form", "New Question"))
self.TAnswer_btn.setText(_translate("Form", "Enter T Answer"))
self.Dat_btn.setText(_translate("Form", "Enter"))
self.label_TAnswer.setText(_translate("Form", "Enter the corect answer:"))
self.Generate_btn.setText(_translate("Form", "Create exam"))
self.NQuestion_btn.setText(_translate("Form", "Enter"))
self.LE_Question.setToolTip(_translate("Form", "Unesite pitanje te pritisnite dugme Unesi pitanje"))
self.Done_btn.setText(_translate("Form", "Done"))
self.label_Question.setText(_translate("Form", "Enter a question:"))


def quiz_name(self):
name = self.LE_datName.text()
return name
def question_generator(self):
question_text = self.LE_Question.text()
if question_text.lower() == self.New_Question_btn.clicked.connect(self.question_generator):
return None
true = self.LE_TAnswer.text()
answer_dict = []
#        while True:
answer = self.LE_Answer.text()
#            if answer.lower() == 'stop':
#                break
answer_dict.append(answer)         
qapair = (question_text, true, answer_dict) 
return qapair,print (qapair)
def question_list_builder(self):
questions = []
while True:
qg_method = self.question_generator()
if qg_method is None:
break
q = (qg_method[0], qg_method[1],qg_method[2]) 
questions.append(q)
return questions
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())

您的代码存在严重的逻辑、概念和编程问题。

首先:即使它看起来不是很重要,也不要使用与内置类型太相似的变量名称(在您的情况下,true(。True(以及False(是内置的布尔值,使用这样的名称(即使使用不同的大小写(可能会导致可读性问题,最终导致调试问题。
始终使用清晰且唯一的变量名称,在您的情况下,它可能类似于correctAnswer.

其次,在处理 UI 元素时不要使用 while 循环。图形界面通常基于事件循环,该循环期望某种类型的交互(来自用户或系统(,然后等待这种情况发生。使用 while 循环(或者,值得一提的是,任何类型的循环,包括for循环或对函数的递归调用(将阻止接收这些事件的能力,使接口无法使用。

第三,你不能在字符串和连接的返回值(通常是None(之间使用if语句:它是苹果和橙子。 当你这样做someSignal.connect(someSlot)你实际上是在告诉Qt,每当发出该someSignal时,它都必须调用该someSlot
想象一下这样的事情:

self.fridge.empty.connect(self.goToMall)

每当冰箱说它是空的时,它就会打电话给goToMall。然后,假设你要去度假,你不想让你的冰箱装满:

self.fridge.empty.disconnect(self.goToMall)

如您所见,connect并没有为您提供任何有用的与字符串进行比较的内容:这就像说"检查我的名字是否等于冰箱空了时我会去商场的事实"。
注意:文档说connect()返回一个Connection对象,以后可以用于断开连接。在我正在使用的 PyQt 的(相当旧的(版本中,它只返回None,但在此期间可能会更改。也就是说,无效的比较问题仍然存在。

第四,不要返回print():它只返回 None,这是不必要的。

最后;切勿pyuic生成的代码混合用于程序。保留该 py 文件原样,并按照文档中的说明将它们作为模块导入。


现在,重新生成使用 Designer 创建的.ui文件,并在另一个文件中使用类似以下内容的内容,该文件将成为您的主程序脚本:

from PyQt5 import QtWidgets
from ui_form import Ui_Form
# I'm using the third method described in the designer documentation given above, 
# the multiple inheritance approach
class QuestionBuilder(QtWidgets.QWidget, Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
self.New_Question_btn.clicked.connect(self.question_generator)
self.questions = []
def question_generator(self):
question_text = self.LE_Question.text()
# I don't really know what you meant by comparing the string with the
# connection, I'm assuming you didn't want to add the same question twice
if self.questions and self.questions[-1].lower() == question_text:
for existing_questions in self.questions:
if question_text.lower() == existing_questions[0]:
print('question already exists, ignoring')
return
correctAnswer = self.LE_TAnswer.text()
answers = []
answers.append(self.LE_Answer.text())
self.questions.append((question_text, correctAnswer, answers))
self.LE_Answer.clear()
self.LE_Question.clear()
self.LE_TAnswer.clear()
print(self.questions)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = QuestionBuilder()
window.show()
sys.exit(app.exec_())

请注意,在上面的例子中,我没有实现正确答案检查(也没有检查所有可能的答案,也没有检查与其他按钮相关的功能(。

让我告诉你,你的方法有几个UI问题,可能会导致你难以调试副作用(以编程方式和用户体验(,我相信最重要的问题是添加太多按钮,其中包含不必要的功能(和不清楚的描述(,你必须考虑 - 不考虑创建一个让最终用户感到困惑的界面。
当单击"输入 T 答案"并且不存在问题时,您会怎么做?如果您单击"输入答案"并且有效答案字段为空怎么办?如果一个答案与另一个答案相似,但字母大小写不同,并且只有一个答案是正确的怎么办?当某些字段无效时,您如何真正检测并通知用户?

我真的相信,在编写实际代码之前,您需要完全重新考虑整个界面,可能使用动态方式添加答案并提供一个系统,允许用户选择其中哪一个是正确的答案。

最新更新