본문 바로가기

Manual

파이썬 tkinter, TOEIC 단어 암기 프로그램

어휘력 향상을 위해 챗GPT에게 토익 필수 어휘 50개를 추천받았습니다.

단어와 한글이 짝을 이룬 텍스트 파일을 만들고,

이 텍스트 파일의 단어를 무작위 순서로 불러와 문제를 내고 답을 입력받아 채점하는 프로그램을 만들었습니다.

입력한 답이 맞으면 다음 단어로 넘어가고

틀렸을 때는 정답을 알려주고 다음 단어로 진행합니다.

모든 단어를 다 풀고 나면 틀렸던 문제만 모아서 다시 순서를 무작위로 섞고 문제를 냅니다.

모든 단어를 다 맞추고 나면 점수를 계산해서 알려줍니다.

 

동작 영상(앞 부분)
동작 영상(끝 부분)

 

만들 코드를 단계별로 정리해 봅니다.

 

1. 필요한 라이브러리 가져오기:

코드는 세 개의 라이브러리를 가져오는 것으로 시작합니다.

  1. pandas(pd로 가져옴): 테이블 형식의 데이터를 처리하는 데 사용되는 강력한 데이터 조작 라이브러리입니다.
  2. random: 퀴즈의 질문을 섞는 데 사용되는 난수를 생성하는 라이브러리입니다.
  3. tkinter(tk로 가져옴): GUI(그래픽 사용자 인터페이스) 응용 프로그램을 만들기 위한 표준 Python 라이브러리입니다.

 

2. Tkinter 창 만들기:

창 이름이 ">> Word Power <<"인 Tkinter 창 객체(창)를 만들고 화면에서 (500, 300)인 위치에 500x350 픽셀로 설정합니다.

 

3. 단어 데이터 로드: 

  1. pandas를 사용하여 텍스트 파일(ToeicWords_1.txt)에서 단어 데이터를 읽고 DataFrame(df)에 저장합니다. 
  2. 텍스트 파일에는 답변에 대한 'ans'와 질문에 대한 'question'의 두 열이 있다고 가정합니다. 
  3. 세 번째 열 'check'는 사용자의 답변을 추적하기 위해 처음에 모든 값이 0으로 설정되어 DataFrame에 추가됩니다.

 

4. GUI 구성 요소 만들기: 

  1. Tkinter를 사용하여 텍스트를 표시하는 레이블(lab1, lab2 등)
  2. 퀴즈 질문을 표시하는 레이블(question_label) 
  3. 사용자가 입력할 항목 위젯(answer_entry) 
  4. 답변을 확인할 수 있는 버튼(check_button)

 

5. GUI 구성 요소 배치: 

  1. place() 메서드를 사용하여 창에서 GUI 구성 요소의 위치를 ​​지정합니다.

 

6. 함수 정의:

퀴즈의 다양한 기능을 처리하는 여러 함수를 정의합니다.

  1. ask_question(): 이 함수는 question_label의 텍스트를 업데이트하고 answer_entry의 사용자 입력을 지워 다음 퀴즈 질문을 표시합니다. 또한 현재 문제 번호를 추적하고 lab3의 텍스트를 업데이트합니다.
  2. check_answer(): 이 함수는 정답과 사용자의 답변을 확인하고 그에 따라 DataFrame의 확인 열을 업데이트합니다. 또한 정답인지 오답인지를 나타내는 메시지를 message_label에 표시합니다. 모든 질문에 답하거나 퀴즈가 끝나면 finish_quiz() 함수를 호출합니다.
  3. finish_quiz(): 이 함수는 오답 문제를 필터링하고, 오답을 입력한 문제가 있는 경우 순서를 섞고 ask_question()을 호출하여 퀴즈를 다시 시작합니다. 모든 질문에 올바르게 답하면 question_label 및 message_label에 완료 메시지를 표시하고 configure() 메서드를 사용하여 check_button 및 answer_entry를 비활성화합니다. 
  4. 바인딩 이벤트: <Return> 키 이벤트를 check_answer() 함수에 바인딩하여 버튼을 클릭하는 대신 Enter 키를 눌러 답변을 확인할 수도 있게 합니다.

 

7. 퀴즈 시작: 

전역 변수(current_question, question_order, num_current 및 wrong_df)의 초기 값을 설정하고 ask_question()을 호출하여 첫 ​​번째 질문을 표시하여 퀴즈를 시작합니다.

 

8. Tkinter 이벤트 루프 실행:

mainloop() 메서드를 호출하여 Tkinter 창의 이벤트 루프를 시작합니다. 이를 통해 사용자는 GUI 구성 요소와 상호 작용하고 창이 닫힐 때까지 이벤트에 응답할 수 있습니다.

 

 

ToeicWords_1.txt
0.00MB

 

import pandas as pd
import random
import tkinter as tk

window = tk.Tk()
window.title(">> Word Power <<")
window.geometry("500x350+500+300")

# 암기할 단어 불러오기
df = pd.read_csv('ToeicWords_1.txt', header=None, names=['ans', 'question'])
df['check'] = 0
src = list(df.index)

lab1=tk.Label(window, text="Increase your vocabulary power!", font=("나눔고딕", 20), width=50, anchor='w' )
lab2=tk.Label(window, text="단어 수 : ", font=("나눔고딕", 14), width=50, anchor='w' )
lab3=tk.Label(window, text="문제 번호 : ", font=("나눔고딕", 14), width=50, anchor='w' )
bar1=tk.Label(window, text="----------------------------------------------------------------------------",
              width=250, anchor='w' )
question_label=tk.Label(window, text="문제 : ", font=("나눔고딕", 22), width=50, anchor='w' )
lab_ans=tk.Label(window, text="Your Answer :  ", font=("나눔고딕", 18), width=100, anchor='w' )
bar2=tk.Label(window, text="----------------------------------------------------------------------------",
              width=250, anchor='w' )
message_label=tk.Label(window, text="Message : ", font=("나눔고딕", 18), wraplength=400, justify='left')
answer_entry=tk.Entry(window, width=18, font=("Arial", 18))

# 배치 -------------------------------------
lab1.place(x=20, y=10)
lab2.place(x=20, y=50)
lab3.place(x=20, y=80)
bar1.place(x=20, y=100)
question_label.place(x=20, y=150)   
lab_ans.place(x=20, y=200)
bar2.place(x=20, y=230)
message_label.place(x=20, y=250)
answer_entry.place(x=140, y=200)

# start quiz
global current_question
current_question = 0
question_order = random.sample(src, len(src))
num_question=len(src)
lab2.config(text="단어 수 : " + str(num_question))
num_current = 0
lab3.config(text="문제 번호 : " + str(num_current))

global incorrect_df

def ask_question():
    # ask next question
    global current_question, num_current, incorrect_df
    if current_question < len(question_order):
        choice = question_order[current_question]
        num_current += 1
        lab3.config(text="문제 번호 : " + str(num_current))
        question_label.config(text="What is the word for ' {} '?".format(df.question[choice]))
        answer_entry.delete(0, tk.END)
        answer_entry.focus()
    else:
        finish_quiz()
    
ask_question()

def check_answer():
    global current_question, incorrect_df
    choice = question_order[current_question]
    your_ans = answer_entry.get()
    if your_ans.lower() == df.ans[choice].lower():
        df.loc[df.index[choice], 'check'] = 1
        message_label.config(text="정답입니다!")
    else:
        message_label.config(text="' "+str(your_ans)+" ' 를 입력하셨는데, \n  정답은  " +str(df.ans[choice].lower()) + " 입니다." )
        
    # move on to next question or finish quiz
    current_question += 1
    if current_question == len(df):
        finish_quiz()
    else:
        ask_question()

check_button = tk.Button(window, text="Check", font=('Arial', 18), command=check_answer)
check_button.place(x=400, y=200)
answer_entry.bind("<Return>", lambda event:  check_answer()) #함수에 인자를 사용하지 않게 

def finish_quiz():
    # filter the questions that were answered incorrectly
    incorrect_df = df[df['check'] != 1]

    # ask the incorrect answers again  
    if len(incorrect_df) > 0:
        global current_question, question_order
        question_order = random.sample(list(incorrect_df.index), len(incorrect_df))
        src = list(incorrect_df.index)
        current_question = 0
        ask_question()
    else:
        answer_entry.delete(0, tk.END)
        question_label.config(text="Quiz Complete!")
        message_label.config(text="축하합니다!!! 모든 문제를 다 맞추셨습니다! \n 점수는 " + str(num_question/num_current*100)+"점!!!")
        check_button.configure(state = 'disabled')
        answer_entry.config(state= "disabled")

window.mainloop()

 

728x90