pythonturtle-graphicspython-turtle

Python Turtle Caption and Button Debugging Help Request


I've been working on a project where I'm building a quiz similar to Kahoot!, featuring questions about Chicago. I've run into a snag: the captions for the answer options aren't visible when the quiz runs. They only appear for a brief moment when an answer button is clicked, and then they disappear again. I want these captions to be visible continuously so users can see them. I'm fairly new to coding and have been stuck on this for a few hours. Could anyone help me figure out how to keep the answer options visible?

from turtle import Screen, Turtle

# Define the quiz questions, options, and answers
quiz_questions = [
    {
        "question": "Which type of crime is most committed in Chicago?",
        "options": ["A. Burglary", "B. Theft", "C. Assault", "D. Vandalism"],
        "answer": "B"
    },
    {
        "question": "What is considered the most popular sport in Chicago according to recent surveys?",
        "options": ["A. Football", "B. Basketball", "C. Baseball", "D. Hockey"],
        "answer": "C"
    },
    {
        "question": "According to public opinion surveys, which public park in Chicago is the most visited?",
        "options": ["A. Lincoln Park", "B. Grant Park", "C. Public Transit", "D. Millenium Park"],
        "answer": "D"
    },
    {
        "question": "What mode of transportation do most Chicagoans prefer for commuting, based on city transportation surveys?",
        "options": ["A. Car", "B. Bicycle", "C. Public Transit", "D. Walking"],
        "answer": "C"
    },
    {
        "question": "Which neighborhood is commonly perceived as the culinary hotspot of Chicago, as per local food surveys?",
        "options": ["A. West Loop", "B. River North", "C. Noise Pollution", "D. Waste Management"],
        "answer": "A"
    },
    {
        "question": "Based on environmental surveys, what is Chicago's biggest environmental concern?",
        "options": ["A. Water Pollution", "B. Air Pollution", "C. Wicker Park", "D. Lincoln Square"],
        "answer": "B"
    },
    {
        "question": "What is the most attended annual event in Chicago, according to event attendance records?",
        "options": ["A. Chicago Marathon", "B. The Taste of Chicago", "C. Lollapalooza", "D. Chicago Auto Show"],
        "answer": "B"
    },
    {
        "question": "Which Chicago museum is rated the highest in visitor satisfaction surveys?",
        "options": ["A. Museum of Science and Industry", "B. Field Museum", "C. The Art Institute of Chicago", "D. Chicago History Museum"],
        "answer": "C"
    },
    {
        "question": "What is the most commonly spoken language in Chicago after English, according to demographic surveys?",
        "options": ["A. Hindi", "B. Chinese", "C. Spanish", "D. Vietnamese"],
        "answer": "C"
    },
    {
        "question": f"Based on urban development surveys, what is Chicago's most \nrapidly growing neighborhood in terms of new construction and business openings?",
        "options": ["A. Lincoln Park", "B. Fulton Market", "C. Hyde Park", "D. Logan Square"],
        "answer": "B"
    }
]

# Initialize the screen
screen = Screen()
screen.setup(width=1.0, height=1.0)
screen.bgcolor('white')

# Create turtles for the question, options, score, and timer
question_turtle = Turtle()
question_turtle.hideturtle()
question_turtle.penup()
question_turtle.goto(0, 250)
question_turtle.color('black')

option_turtles = []
option_texts = []  # List to hold the text turtles
option_colors = ['red', 'black', 'blue', 'green']
for i in range(4):
    option_turtle = Turtle(shape='square')
    option_turtle.penup()
    option_turtle.shapesize(stretch_wid=5, stretch_len=20)  # Larger buttons
    option_turtle.color(option_colors[i])
    option_turtle.goto(0, 150 - i * 120)  # Adjust the position
    
    # Create a turtle for the option text
    text_turtle = Turtle()
    text_turtle.hideturtle()
    text_turtle.penup()
    text_turtle.goto(option_turtle.xcor(), option_turtle.ycor() - 20)
    text_turtle.color('white')  # White text color
    
    option_turtles.append(option_turtle)
    option_texts.append(text_turtle)  # Add to the list of text turtles

score_turtle = Turtle()
score_turtle.hideturtle()
score_turtle.penup()
score_turtle.goto(200, 330)
score_turtle.color('black')

timer_turtle = Turtle()
timer_turtle.hideturtle()
timer_turtle.penup()
timer_turtle.goto(-200, 330)
timer_turtle.color('purple')

# Draw timer circle
timer_circle = Turtle()
timer_circle.hideturtle()
timer_circle.penup()
timer_circle.color('purple')
timer_circle.goto(-200, 220)
timer_circle.shape('circle')
timer_circle.shapesize(stretch_wid=3, stretch_len=3)  # Adjust size as needed


def draw_question(question_number, question, options):
    question_turtle.clear()
    for i, option_turtle in enumerate(option_turtles):
        option_turtle.showturtle()

        # Clear the old text and write the new one
        option_texts[i].clear()
        option_texts[i].write(quiz_questions[current_question_index[0]-1]['options'][i], align="center", font=("Arial", 14, "bold"))

    question_turtle.write(f"Question {question_number}: {question}", align="center", font=("Arial", 18, "normal"))

def show_score(score):
    score_turtle.clear()
    score_turtle.write(f"Score: {score}/10", align="center", font=("Arial", 18, "normal"))

def show_timer(time_left):
    timer_turtle.clear()
    timer_turtle.write(f"Time: {time_left}s", align="center", font=("Arial", 18, "normal"))

def handle_option_click(x, y, answer, correct_answer, callback):
    if answer == correct_answer:
        score[0] += 1  # Increment score if answer is correct
    show_score(score[0])
    callback()  # Call the callback function to proceed to the next question
    # Redraw text immediately after handling click
    draw_current_options()

def draw_current_options():
    for i in range(4):
        option_texts[i].clear()
        if current_question_index[0] < len(quiz_questions):  # Ensure index is within bounds
            option_texts[i].write(quiz_questions[current_question_index[0]]['options'][i], align="center", font=("Arial", 16, "bold"))

current_question_index = 0

def setup_question(question_info):
    current_question_index[0] += 1  # Increment question index
    correct_answer = question_info['answer']
    for i, option_turtle in enumerate(option_turtles):
        option_turtle.onclick(lambda x, y, a=chr(65+i), ca=correct_answer: handle_option_click(x, y, a, ca, next_question))
    draw_question(current_question_index[0], question_info['question'], question_info['options'])

def next_question():
    if quiz_questions and current_question_index[0] < len(quiz_questions):
        question_info = quiz_questions[current_question_index[0]]
        setup_question(question_info)
    else:
        finish_quiz()

def update_timer():
    if time_elapsed[0] < 100:
        time_elapsed[0] += 1
        show_timer(100 - time_elapsed[0])
        screen.ontimer(update_timer, 1000)
    else:
        finish_quiz()

def finish_quiz():
    question_turtle.goto(0, 0)
    question_turtle.write("Quiz Over! Final Score: {}/10".format(score[0]), align="center", font=("Arial", 24, "bold"))
    for option_turtle in option_turtles:
        option_turtle.hideturtle()

score = [0]
time_elapsed = [0]  # Timer counter
current_question_index = [0]  # Track current question number

# Show initial score
show_score(score[0])  # Initialize score display
show_timer(100 - time_elapsed[0])

if quiz_questions:
    next_question()  # Start the quiz
    update_timer()  # Start the timer

screen.mainloop()

I have been trying to solve this problem using chatgpt, but no success whatsoever


Solution

  • The issue you describe in the comments to the other answer is caused by the fact that you paint texts over the turtles making clicks reaching the turtles only if the mouse is not positioned over the text. This explains how it comes that sometimes it worked and sometimes not - it depended on where exactly you have clicked and how large was the text. If you hit the text, nothing happened. If you hit the text-free edge of the turtle you were getting response.

    I have rewritten the code a bit and placed the text outside the colored areas to avoid this effect:

    from turtle import Screen, Turtle
    quiz_questions = [
        (    None, None, None ), # Placeholder to make question numbering start with ONE
        (    "Which type of crime is most committed in Chicago?",  ["A. Burglary", "B. Theft", "C. Assault", "D. Vandalism"],  "B" ),
        (    "What is considered the most popular sport in Chicago according to recent surveys?",  ["A. Football", "B. Basketball", "C. Baseball", "D. Hockey"],  "C" ),
        (    "According to public opinion surveys, which public park in Chicago is the most visited?",  ["A. Lincoln Park", "B. Grant Park", "C. Public Transit", "D. Millenium Park"],  "D" ),
        (    "What mode of transportation do most Chicagoans prefer for commuting, based on city transportation surveys?", ["A. Car", "B. Bicycle", "C. Public Transit", "D. Walking"], "C" ),
        (    "Which neighborhood is commonly perceived as the culinary hotspot of Chicago, as per local food surveys?",  ["A. West Loop", "B. River North", "C. Noise Pollution", "D. Waste Management"], "A" ),
        (    "Based on environmental surveys, what is Chicago's biggest environmental concern?",  ["A. Water Pollution", "B. Air Pollution", "C. Wicker Park", "D. Lincoln Square"],  "B" ),
        (   "What is the most attended annual event in Chicago, according to event attendance records?",  ["A. Chicago Marathon", "B. The Taste of Chicago", "C. Lollapalooza", "D. Chicago Auto Show"], "B" ),
        (   "Which Chicago museum is rated the highest in visitor satisfaction surveys?",  ["A. Museum of Science and Industry", "B. Field Museum", "C. The Art Institute of Chicago", "D. Chicago History Museum"],  "C" ),
        (   "What is the most commonly spoken language in Chicago after English, according to demographic surveys?",  ["A. Hindi", "B. Chinese", "C. Spanish", "D. Vietnamese"],  "C" ),
        (    f"Based on urban development surveys, what is Chicago's most \nrapidly growing neighborhood in terms of new construction and business openings?",  ["A. Lincoln Park", "B. Fulton Market", "C. Hyde Park", "D. Logan Square"],  "B" )
    ]
    screen = Screen()
    screen.setup(width=1.0, height=1.0)
    screen.bgcolor('lightgreen')
    question_turtle = Turtle(); question_turtle.hideturtle(); question_turtle.penup()
    question_turtle.goto(0, 250); question_turtle.color('black')
    option_turtles = []
    option_texts = []  # List to hold the text turtles
    option_colors = ['red', 'yellow', 'blue', 'green']
    for i in range(4):
        option_turtle = Turtle(shape='square')
        option_turtle.penup()
        option_turtle.shapesize(stretch_wid=5, stretch_len=10)  # Buttons are Turtles
        option_turtle.color(option_colors[i])
        option_turtle.goto(-150, 150 - i * 120)
        text_turtle = Turtle()
        text_turtle.hideturtle()
        text_turtle.penup()
        text_turtle.goto(option_turtle.xcor()+200, option_turtle.ycor() - 20)
        text_turtle.color('brown') 
        option_turtles.append(option_turtle)
        option_texts.append(text_turtle) 
    # ================================
    score_turtle = Turtle()
    score_turtle.hideturtle()
    score_turtle.penup()
    score_turtle.goto(200, 330)
    score_turtle.color('black')
    
    timer_turtle = Turtle()
    timer_turtle.hideturtle()
    timer_turtle.penup()
    timer_turtle.goto(-200, 330)
    timer_turtle.color('purple')
    
    # Draw timer circle
    timer_circle = Turtle()
    timer_circle.hideturtle()
    timer_circle.penup()
    timer_circle.color('purple')
    timer_circle.goto(-200, 220)
    timer_circle.shape('circle')
    timer_circle.shapesize(stretch_wid=3, stretch_len=3) 
    
    def ask_question( x=None, y=None, answer=None ):
        global correct_answer, current_question_index, score
        if current_question_index >= 1 :
            if  answer == correct_answer :
                score += 1
        current_question_index += 1
        question_info = quiz_questions[current_question_index]
        question, options, correct_answer =question_info
        score_turtle.clear()
        score_turtle.write(f"Score: {score}/10", align="center", font=("Arial", 18, "normal"))
        if current_question_index < len(quiz_questions):
            question_turtle.clear()
            question_turtle.write(f"Question {current_question_index}: {question}", align="center", font=("Arial", 18, "normal"))
            for i, option_turtle in enumerate(option_turtles):
                option_texts[i].clear()
                option_texts[i].write( options[i], align="left", font=("Arial", 16, "bold"))
        else:
            for indx, option_turtle in enumerate(option_turtles) :
                option_turtle.hideturtle()
                text_turtle[indx].clear()
            question_turtle.goto(0, 0)
            question_turtle.write("Quiz Over! Final Score: {}/10".format(score), align="center", font=("Arial", 24, "bold"))
    
    def update_timer():
        global time_elapsed
        if time_elapsed < 100:
            time_elapsed += 1
            timer_turtle.clear()
            timer_turtle.write(f"Time: {100-time_elapsed}s", align="center", font=("Arial", 18, "normal"))
            screen.ontimer(update_timer, 1000)
        else:
            for option_turtle in option_turtles:
                option_turtle.hideturtle()
            question_turtle.goto(0, 0)
            question_turtle.write("Quiz Over! Final Score: {}/10".format(score), align="center", font=("Arial", 24, "bold"))
    
    score = 0
    time_elapsed = 0  # Timer counter
    current_question_index = 0  # Track current question number
    def on_option_turtle_A(x,y): ask_question(x,y,"A")
    def on_option_turtle_B(x,y): ask_question(x,y,"B")
    def on_option_turtle_C(x,y): ask_question(x,y,"C")
    def on_option_turtle_D(x,y): ask_question(x,y,"D")
    option_turtles[0].onclick( on_option_turtle_A  )
    option_turtles[1].onclick( on_option_turtle_B  )
    option_turtles[2].onclick( on_option_turtle_C  )
    option_turtles[3].onclick( on_option_turtle_D  )
    ask_question()  # Start the quiz
    update_timer()  # Start the timer
    
    screen.mainloop()
    

    enter image description here