Search code examples
pythontkintertkinter-button

The text changes when i click the "next" button, but it continues the past text after the new text in displayed. how do i fix this?


I am making a text game with pictures with my group for a project. I implemented a typewriter effect into the game, so when a text is diplayed in the label, it types the text out. I made a "next" button to change the text to the next string, and it also works. My problem is that if the player clicks on next too quickly, they do get the next string, but the remaining text of the string before the new string the displays after the new string.

I used blackbox for helping me with issues in the "next" button, and I used stack overflow with the typewriter. the rest is all me. I am using Tkinter to make the game in VScode.

I need the button to be disabled while the text writes out.

Here is the piece of code (Without flag because i deleted that part):

import tkinter as tk
from tkinter import PhotoImage, Button
import time

# Creating window for game
window = tk.Tk()
window.title('Untitled Game')
window.geometry('1280x720')


def cmd_start():
    global Label_1, btnContinue
    btnStart.place_forget()
    create_typewriter_button()

def create_typewriter_button():
    global Label_1, btnContinue
    #Create label
    Label_1 = tk.Label(window, font=('Arial', 15, 'bold'))
    Label_1.place(x=10 ,y=450)

    #Create button
    btnContinue = Button(window, width=5, height=2, text="Next", font=('Arial', 12, 'bold'))
    btnContinue.place(x=1080, y=450)
    btnContinue.config(bg='Light grey')

    #Create texts
    Texts = [
            "Text 1 here!",
            "Text 2 here?",
            "Text 3 here.",
            "Text 4 here,",
            "Text 5 here@"
        ]
    index = 0
    
    #Typewriter code
    def cmd_typewriter_1(text):
        Label_1.config(text="")
        for char in text:
            Label_1.config(text=Label_1.cget("text") + char)
            window.update()
            window.after(50) # use after instead of time.sleep
    
    def cmd_forward():
        nonlocal index
        index = (index + 1)
        if index > len(Texts):
            index = len(Texts) - 1
        cmd_typewriter_1(Texts[index])
        
    
    btnContinue.config(command=lambda: cmd_typewriter_1(Texts[index], cmd_forward()))

# Start Game
def cmd_start_game():
    cmd_start()

btnStart = Button(window, width=10, height=2, text="Start", font=('Arial', 12, 'bold'), command=cmd_start_game)
btnStart.place(x=100, y=50)
btnStart.config(bg='Light grey')

window.mainloop()

Solution

  • In your cmd_typewriter_1 function, you should disable the 'next' button at the beginning of the function, and re-enable the button at the end (when the text finishes typing).

    You can do this by calling btnContinue.config(state=) the state should be 'disabled' to disable it, and 'normal' to re-enable it.

    def cmd_typewriter_1(text):
        btnContinue.config(state='disabled')
        Label_1.config(text="")
        for char in text:
            Label_1.config(text=Label_1.cget("text") + char)
            window.update()
            window.after(50)
        btnContinue.config(state='normal')