Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Multiple choice quiz or exam generator



  • I'm trying to create a script or app for creating multiple choice quizzes. It would allow the user to enter a question, then give a true answer and a number of answers to choose from. The user could repeat that process as many times as he wishes. Then the user would need to enter the number of questions that the created quiz would have. In the end the quiz would be saved as a pdf or word document. All of this would nee a gui made in Qt. So far I have made most of the quiz script and it is working properly. (still need to figure out how to add a,b,c... in front of answers and save to pdf but that shoudn't be a problem). The gui is also done and I think it should work properly.

    The problem is I don't know how to connect the quiz script with the gui. I tried many things and none of them work.

    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 code:

    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_())
    

    Any help is appreciated :)


  • Banned

    A big part of your problem is that you using Qt Creator or Designer to build your GUI -- and I doubt you are using it because you need it for the purpose it was designed for -- and while it might seem easy on the surface it creates code not meant to be worked with -- further creating a GUI using python-qt as it was meant to be used is actually fairly easy. I will see if I can address your issue by coding as it should have been coded but that usually takes a bit of time.



  • @Denni-0 I could probably build the gui with pyqt5 but I still would have the problem of connecting everything. All the tutorails that I have found on youtube are for simple problems.


  • Banned

    Great that is good to hear but for me to dig into this I first ditch the Designer garbage as my first step as that helps me see more clearly what you are striving to do. With that said here is your GUI Code with all the unnecessary code removed and the code slightly restructured to be a bit friendlier -- now I am not done mind you but this is just to show you how to go from Designer code to more python-qt code -- my next step will require a few questions which I will ask in my next post

    from PyQt5.QtCore    import Qt
    #from PyQt5.QtGui     import 
    from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QFrame, QLabel
    from PyQt5.QtWidgets import QPushButton, QLineEdit
    
    class UI_Form(QWidget):
        def __init__(self) :
            QWidget.__init__(self)
    
            self.setWindowTitle("Kolokvij")
            self.resize(1077, 943)
    
            self.line_3 = QFrame()
            self.line_3.setFrameShape(QFrame.VLine)
            self.line_3.setFrameShadow(QFrame.Sunken)
    
            self.line_4 = QFrame()
            self.line_4.setFrameShape(QFrame.VLine)
            self.line_4.setFrameShadow(QFrame.Sunken)
    
            self.Answer_btn = QPushButton("Enter Answer")
            self.Answer_btn.pressed.connect(self.Clear_LE_Answer)
    
            self.LE_datName = QLineEdit()
    
            self.label_datName = QLabel("Enter the name of the file:")
    
            self.Question_btn = QPushButton("Enter Question")
            self.Question_btn.setToolTip("Pritisnite ovo")
    
            self.LE_TAnswer = QLineEdit()
    
            self.LE_Answer = QLineEdit()
    
            self.line_2 = QFrame()
            self.line_2.setFrameShape(QFrame.HLine)
            self.line_2.setFrameShadow(QFrame.Sunken)
    
            self.label_NQuestion = QLabel("Number of questions in exam:")
    
            self.label_Answer = QLabel("Enter all the possible answers:")
            self.label_Answer.setFrameShape(QFrame.NoFrame)
            self.label_Answer.setTextFormat(Qt.AutoText)
            self.label_Answer.setScaledContents(False)
    
            self.LE_NQuestions = QLineEdit()
    
            self.New_Question_btn = QPushButton("New Question")
            self.New_Question_btn.clicked.connect(self.NewQuestionReset)
    
            self.TAnswer_btn = QPushButton("Enter T Answer")
            self.TAnswer_btn.clicked.connect(self.IDoNothing)
    
            self.line = QFrame()
            self.line.setFrameShape(QFrame.HLine)
            self.line.setFrameShadow(QFrame.Sunken)
    
            self.Dat_btn = QPushButton("Enter")
            self.Dat_btn.clicked.connect(self.IDoNothing)
    
            self.label_TAnswer = QLabel("Enter the corect answer:")
    
            self.Generate_btn = QPushButton("Create exam")
            self.Generate_btn.clicked.connect(self.CreateExamSetup)
    
            self.NQuestion_btn = QPushButton("Enter")
            self.NQuestion_btn.clicked.connect(self.IDoNothing)
    
            self.LE_Question = QLineEdit()
            self.LE_Question.setText("")
            self.LE_Question.setToolTip("Unesite pitanje te pritisnite dugme Unesi pitanje")
            self.LE_Question.setToolTipDuration(-1)
            
            self.Done_btn = QPushButton("Done")
            self.Done_btn.clicked.connect(self.IDoNothing)
    
            self.line_okv2 = QFrame()
            self.line_okv2.setLineWidth(5)
            self.line_okv2.setFrameShape(QFrame.HLine)
            self.line_okv2.setFrameShadow(QFrame.Sunken)
    
            self.line_okv1 = QFrame()
            self.line_okv1.setFrameShadow(QFrame.Sunken)
            self.line_okv1.setLineWidth(3)
            self.line_okv1.setFrameShape(QFrame.HLine)
    
            self.label_Question = QLabel("Enter a question:")
    
            self.gridLayout_2 = QGridLayout()
            self.gridLayout_2.addWidget(self.Answer_btn, 4, 2, 1, 1)
            self.gridLayout_2.addWidget(self.LE_datName, 7, 1, 1, 1)
            self.gridLayout_2.addWidget(self.label_datName, 7, 0, 1, 1)
            self.gridLayout_2.addWidget(self.Question_btn, 1, 2, 1, 1)
            self.gridLayout_2.addWidget(self.LE_TAnswer, 3, 1, 1, 1)
            self.gridLayout_2.addWidget(self.LE_Answer, 4, 1, 1, 1)
            self.gridLayout_2.addWidget(self.line_2, 8, 0, 1, 4)
            self.gridLayout_2.addWidget(self.label_NQuestion, 9, 0, 1, 1)
            self.gridLayout_2.addWidget(self.label_Answer, 4, 0, 1, 1)
            self.gridLayout_2.addWidget(self.LE_NQuestions, 9, 1, 1, 1)
            self.gridLayout_2.addWidget(self.New_Question_btn, 4, 3, 1, 1)
            self.gridLayout_2.addWidget(self.TAnswer_btn, 3, 2, 1, 1)
            self.gridLayout_2.addWidget(self.line, 6, 0, 1, 4)
            self.gridLayout_2.addWidget(self.Dat_btn, 7, 2, 1, 1)
            self.gridLayout_2.addWidget(self.label_TAnswer, 3, 0, 1, 1)
            self.gridLayout_2.addWidget(self.Generate_btn, 9, 3, 1, 1)
            self.gridLayout_2.addWidget(self.NQuestion_btn, 9, 2, 1, 1)
            self.gridLayout_2.addWidget(self.LE_Question, 1, 1, 1, 1)
            self.gridLayout_2.addWidget(self.Done_btn, 5, 2, 1, 1)
            self.gridLayout_2.addWidget(self.line_okv2, 10, 0, 1, 4)
            self.gridLayout_2.addWidget(self.line_okv1, 0, 0, 1, 4)
            self.gridLayout_2.addWidget(self.label_Question, 1, 0, 1, 1)
    
            self.gridLayout = QGridLayout()
            self.gridLayout.addWidget(self.line_3, 0, 4, 1, 1)
            self.gridLayout.addWidget(self.line_4, 0, 0, 1, 1)
            self.gridLayout.addLayout(self.gridLayout_2, 0, 1, 1, 1)
            
            self.setLayout(self.gridLayout)
    
        def IDoNothing(self):
            print('I do nothing not sure why I exist?')
    
        def Clear_LE_Answer(self):
            self.LE_Answer.clear()
    
        def NewQuestionReset(self):
            self.LE_Question.clear()
            self.LE_TAnswer.clear()
            self.LE_Answer.clear()
    
        def CreateExamSetup(self):
            self.LE_NQuestions.clear()
            self.LE_datName.clear()
        
    
        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 = []
            answer = self.LE_Answer.text()
            answer_dict.append(answer)         
            qapair = (question_text, true, answer_dict) 
            print (qapair)
    
            return 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__":
        EvntThred = QApplication([])
    
        Form = UI_Form()
        Form.show()
    
        EvntThred.exec()
    
      # If anyone wants more extensive free help I run an online lab-like classroom-like 
      # message server feel free and drop by you will not be able to post until I clear 
      # you as a student as this prevents spammers so if interested here is the invite
      # https://discord.gg/3D8huKC
    

  • Banned

    Okay now you posted two code sets -- both of which had __main__ in them -- which one is supposed to be the actual main program and which is the add on code --- I am thinking your GUI Code is your main and the other one was supposed to be something that supported the GUI Code -- is that correct?



  • First I made the quiz code and the __main__ was supposed to be only for that code. GUI code is really the main code. I'm using the quiz code just as a reference or help of some sort. And it is easier to see what works and what not :)
    Quiz code __main__ was just copied from another code from github to create the output file containing the desired Q&A, but it is not necessary to save the output file as a .json file, .txt will do just fine. GUI code main was automatically created while converting GUI.ui file to GUI.py file.


  • Banned

    Okay while that works for making a MUC (Minimal Useable Code) and testing aspects of the code (a good thing) when presenting it as a full question you kind of need to create the MRE (Minimal Reproducible Example) so that we can better help you solve your problem. Okay I have the GUI Code = Main and the other code an external module you will import into Main I will set that up accordingly and post an example


Log in to reply