Tkinter 및 Open Trivia DB를 사용한 GUI Q&A 애플리케이션


이 블로그에서는 Python 내장 모듈 빌드Graphical User Interface(GUI) 퀴즈 어플리케이션 사용법을 학습합니다.임무는 여러 가지 선택 문제를 묻고 사용자의 답을 수집하여 결과를 표시하는 것이다.GUI를 작성하기 전에 먼저 여러 가지 선택 문항, 정답 및 Tkinter의 옵션을 얻는 방법을 알아보겠습니다.개방형 자질구레한 데이터베이스는 프로그래밍 프로젝트에 사용할 수 있는 완전한 무료 JSON API를 제공합니다.이 API를 사용하려면 API 키가 필요하지 않습니다.임무를 더욱 재미있게 하기 위해서 우리는 무작위로 순서를 선택할 것이다.
제작하고 있는 내용을 확인하려면 프레젠테이션 비디오를 보십시오.
이 프로젝트에는 다음과 같은 모듈과 개념이 적용됩니다.
  • Open Trivia DB API
  • tkinter module
  • random module
  • requests library
  • 우리는 서로 다른 기능을 서로 다른 종류와 파일로 구분할 것이다.

    파이썬 클래스 흥미진진한 문제


    위에서 설명한 대로 열려 있는 사소한 DB API를 사용하여 문제를 해결합니다. 로 가서 문제 수량, 종류와 난이도를 선택하세요.문제 유형은 다중 선택이고 인코딩은 기본 인코딩이어야 합니다.Generate API URL을 클릭하면 API URL이 표시됩니다.
    API URL 예: https://opentdb.com/api.php?amount=10&type=multiple문제를 얻기 위해 requests 모듈을 사용합니다.다음과 같이 설치할 수 있습니다.
    $ pip install requests
    
    테스트 질문과 답을 얻기 위해 위에 생성된 API URL을 사용하는 파이썬 파일quiz_data.py을 만듭니다.
    import requests
    
    parameters = {
        "amount": 10,
        "type": "multiple"
    }
    
    response = requests.get(url="https://opentdb.com/api.php", params=parameters)
    question_data = response.json()["results"]
    
    위 스크립트에서 URL에 직접 amount 인자와 type 인자를 추가하지 않고 parameters 사전을 만들고 값을 추가했습니다.그런 다음 열린 DB API URL의 요청 라이브러리를 사용하여 GET 요청을 보냅니다.JSON 응답 예는 다음과 같습니다.
    {
      "response_code": 0,
      "results": [
        {
          "category": "Entertainment: Video Games",
          "type": "multiple",
          "difficulty": "hard",
          "question": "What was the name of the hero in the 80s animated video game 'Dragon's Lair'?",
          "correct_answer": "Dirk the Daring",
          "incorrect_answers": ["Arthur", "Sir Toby Belch", "Guy of Gisbourne"]
        },
        {
          "category": "Entertainment: Video Games",
          "type": "multiple",
          "difficulty": "medium",
          "question": "Which of these game franchises were made by Namco?",
          "correct_answer": "Tekken",
          "incorrect_answers": ["Street Fighter", "Mortal Kombat", "Dragon Quest"]
        }
      ]
    }
    
    
    JSON 데이터에는 두 개의 키response_coderesults가 있는 사전이 포함되어 있다.response_code 개발자에게 API가 무엇을 하고 있는지 알려줍니다.results는 우리가 흥미를 느끼는 목록이다.따라서 결과의 값을 변수question_data에 저장합니다.

    그들의 API 문제 모델


    문제 모델은 Python류일 뿐 세 가지 속성question_text,correct_answerchoices가 있다.문제의 텍스트는 문제이고, 정답은 이 문제의 정답이며, 옵션은 이 문제의 옵션 목록이다.question_model.py 파일을 만들고 클래스를 만듭니다.
    class Question:
        def __init__ (self, question: str, correct_answer: str, choices: list):
            self.question_text = question
            self.correct_answer = correct_answer
            self.choices = choices
    
    

    퀴즈


    말 그대로 QuizBrain는 응용 프로그램의 뇌다.quiz_brain.py 파일을 만들고 다음 코드를 추가합니다.
    class QuizBrain:
    
        def __init__ (self, questions):
            self.question_no = 0
            self.score = 0
            self.questions = questions
            self.current_question = None
    
        def has_more_questions(self):
            """To check if the quiz has more questions"""
    
            return self.question_no < len(self.questions)
    
        def next_question(self):
            """Get the next question by incrementing the question number"""
    
            self.current_question = self.questions[self.question_no]
            self.question_no += 1
            q_text = self.current_question.question_text
            return f"Q.{self.question_no}: {q_text}"
    
        def check_answer(self, user_answer):
            """Check the user answer against the correct answer and maintain the score"""
    
            correct_answer = self.current_question.correct_answer
            if user_answer.lower() == correct_answer.lower():
                self.score += 1
                return True
            else:
                return False
    
        def get_score(self):
            """Get the number of correct answers, wrong answers and score percentage."""
    
            wrong = self.question_no - self.score
            score_percent = int(self.score / self.question_no * 100)
            return (self.score, wrong, score_percent)
    
    
    QuizBrain 과정은 questions, 문제 목록을 포함한다.그 밖에 question_noscore 속성용0으로 초기화되었고 current_question은 처음None으로 설정되었다.
    첫 번째 방법has_more_questions()은 더 많은 문제가 있는지 검사한다.다음 방법next_question()은 색인questionsquestion_no 목록에서 문제를 얻은 다음 포맷된 문제를 되돌려 주는 속성을 증가question_no합니다.check_answer() 방법은 user_answer를 매개 변수로 하고 사용자의 답안이 정확한지 검사한다.점수를 유지하고 브리 값을 되돌려줍니다.마지막 방법get_score()은 정답, 오답, 점수의 백분율을 되돌려줍니다.

    사용자 인터페이스 테스트


    응용 프로그램의 사용자 인터페이스를 만드는 다음 부분으로 넘어가겠습니다.quiz_ui.py 파일을 만들고 다음을 추가합니다.
    from tkinter import Tk, Canvas, StringVar, Label, Radiobutton, Button, messagebox
    from quiz_brain import QuizBrain
    
    THEME_COLOR = "#375362"
    
    class QuizInterface:
    
        def __init__ (self, quiz_brain: QuizBrain) -> None:
            self.quiz = quiz_brain
            self.window = Tk()
            self.window.title("iQuiz App")
            self.window.geometry("850x530")
    
            # Display Title
            self.display_title()
    
            # Creating a canvas for question text, and dsiplay question
            self.canvas = Canvas(width=800, height=250)
            self.question_text = self.canvas.create_text(400, 125,
                                                         text="Question here",
                                                         width=680,
                                                         fill=THEME_COLOR,
                                                         font=(
                                                             'Ariel', 15, 'italic')
                                                         )
            self.canvas.grid(row=2, column=0, columnspan=2, pady=50)
            self.display_question()
    
            # Declare a StringVar to store user's answer
            self.user_answer = StringVar()
    
            # Display four options(radio buttons)
            self.opts = self.radio_buttons()
            self.display_options()
    
            # To show whether the answer is correct or wrong
            self.feedback = Label(self.window, pady=10, font=("ariel", 15, "bold"))
            self.feedback.place(x=300, y=380)
    
            # Next and Quit Button
            self.buttons()
    
            # Mainloop
            self.window.mainloop()
    
        def display_title(self):
            """To display title"""
    
            # Title
            title = Label(self.window, text="iQuiz Application",
                          width=50, bg="green", fg="white", font=("ariel", 20, "bold"))
    
            # place of the title
            title.place(x=0, y=2)
    
        def display_question(self):
            """To display the question"""
    
            q_text = self.quiz.next_question()
            self.canvas.itemconfig(self.question_text, text=q_text)
    
        def radio_buttons(self):
            """To create four options (radio buttons)"""
    
            # initialize the list with an empty list of options
            choice_list = []
    
            # position of the first option
            y_pos = 220
    
            # adding the options to the list
            while len(choice_list) < 4:
    
                # setting the radio button properties
                radio_btn = Radiobutton(self.window, text="", variable=self.user_answer,
                                        value='', font=("ariel", 14))
    
                # adding the button to the list
                choice_list.append(radio_btn)
    
                # placing the button
                radio_btn.place(x=200, y=y_pos)
    
                # incrementing the y-axis position by 40
                y_pos += 40
    
            # return the radio buttons
            return choice_list
    
        def display_options(self):
            """To display four options"""
    
            val = 0
    
            # deselecting the options
            self.user_answer.set(None)
    
            # looping over the options to be displayed for the
            # text of the radio buttons.
            for option in self.quiz.current_question.choices:
                self.opts[val]['text'] = option
                self.opts[val]['value'] = option
                val += 1
    
        def next_btn(self):
            """To show feedback for each answer and keep checking for more questions"""
    
            # Check if the answer is correct
            if self.quiz.check_answer(self.user_answer.get()):
                self.feedback["fg"] = "green"
                self.feedback["text"] = 'Correct answer! \U0001F44D'
            else:
                self.feedback['fg'] = 'red'
                self.feedback['text'] = ('\u274E Oops! \n'
                                         f'The right answer is: {self.quiz.current_question.correct_answer}')
    
            if self.quiz.has_more_questions():
                # Moves to next to display next question and its options
                self.display_question()
                self.display_options()
            else:
                # if no more questions, then it displays the score
                self.display_result()
    
                # destroys the self.window
                self.window.destroy()
    
        def buttons(self):
            """To show next button and quit button"""
    
            # The first button is the Next button to move to the
            # next Question
            next_button = Button(self.window, text="Next", command=self.next_btn,
                                 width=10, bg="green", fg="white", font=("ariel", 16, "bold"))
    
            # palcing the button on the screen
            next_button.place(x=350, y=460)
    
            # This is the second button which is used to Quit the self.window
            quit_button = Button(self.window, text="Quit", command=self.window.destroy,
                                 width=5, bg="red", fg="white", font=("ariel", 16, " bold"))
    
            # placing the Quit button on the screen
            quit_button.place(x=700, y=50)
    
        def display_result(self):
            """To display the result using messagebox"""
            correct, wrong, score_percent = self.quiz.get_score()
    
            correct = f"Correct: {correct}"
            wrong = f"Wrong: {wrong}"
    
            # calculates the percentage of correct answers
            result = f"Score: {score_percent}%"
    
            # Shows a message box to display the result
            messagebox.showinfo("Result", f"{result}\n{correct}\n{wrong}")
    
    
    응, 이것은 매우 큰 각본이지만, 자세히 보면 이해하기 쉽다.코드에 좋은 문서 기록이 있다.

    물건을 챙기다


    모든 구성 요소가 통합될 준비가 되었으므로 main.py 파일을 만들고 다음 항목을 추가합니다.
    from question_model import Question
    from quiz_data import question_data
    from quiz_brain import QuizBrain
    from quiz_ui import QuizInterface
    from random import shuffle
    import html
    
    question_bank = []
    for question in question_data:
        choices = []
        question_text = html.unescape(question["question"])
        correct_answer = html.unescape(question["correct_answer"])
        incorrect_answers = question["incorrect_answers"]
        for ans in incorrect_answers:
            choices.append(html.unescape(ans))
        choices.append(correct_answer)
        shuffle(choices)
        new_question = Question(question_text, correct_answer, choices)
        question_bank.append(new_question)
    
    quiz = QuizBrain(question_bank)
    
    quiz_ui = QuizInterface(quiz)
    
    print("You've completed the quiz")
    print(f"Your final score was: {quiz.score}/{quiz.question_no}")
    
    
    생성된 다른 파일에서 모든 클래스를 가져옵니다.이 밖에도 shuffle 모듈과 random 모듈의 html 방법이 필요합니다.우리는 목록이 하나 있다question_bank.우리는 question_data 파일에서 받은 quiz_data.py를 교체하고 있다.예시 응답을 보면, 예를 들어 &#039;Dragon&#039 텍스트를 발견할 수 있습니다.html.unescape 방법으로 은폐해야 한다.우리는 정답과 오답을 포함하는 choices 목록을 가지고 있다.shuffle 모듈의 random 방법을 사용하여 목록을 씻을 것입니다.카드를 씻은 후에 우리는 Question 파일의 quiz_model.py 모델을 사용하여 문제를 만들고 question_bank 목록에 추가합니다.
    그 다음에 QuizBrain 클래스의 대상quiz을 만들 것입니다. 일련의 문제가 필요합니다.그래서 우리는 question_bank에 그것을 전달할 것이다.다음에, 우리는QuizInterface 클래스의 대상 quiz_ui 을 만들 것입니다. 이것은QuizBrain 클래스의 대상이 필요하기 때문에 새로 만든 quiz 대상을 전달합니다.
    이제 모든 것이 준비되었으니 우리는 프로그램을 실행할 수 있다.
    $ python main.py
    
    캡처




    결론


    네가 이 테스트 프로그램을 좋아하길 바란다.원하는 경우 UI를 보다 매력적으로 만드는 기능을 추가할 수 있습니다.
    코드 라이브러리:
    https://github.com/ashutoshkrris/GUI-Quiz-Tkinter

    좋은 웹페이지 즐겨찾기