0

Tkinter ignores root.after The countdown animation plays but it ignores the delay and does everything that's after root.after before the countdown is over

All tests suggest that the countdown is happening and the variable is changing, it just skips the delay

def StartTheSpam():
    global TimeLable, ErrorLabel
    #destoryes error labels and the countdown timer
    try:
        for child in root.winfo_children():
            if child == TimeLable or child == ErrorLabel:
                child.destroy()
    except NameError:
        pass
    #needed for fail-safe 1
    mouse = MouseController()

    countdown_value = 5
    counter = tk.StringVar()
    counter.set(countdown_value)
    TimeLable = tk.Label(frame, textvariable=counter, padx=10, pady=5, bg=Modes[mode.get()][3]['background'], fg=Modes[mode.get()][2]['text'])
    TimeLable.pack()

    #coundown
    for countdown in range(1, countdown_value):
        root.after(1000 * countdown, counter.set, countdown_value - countdown)
    x = 100
    y = 100
    try:
        with open(PreferencesStorage['FilePath'], 'r') as SpamText: 
            while PreferencesStorage['loop']:
                for word in SpamText:
                    #fail safe 1
                    if x < 21 and y < 21:
                        break
                    TempX, TempY = mouse.position
                    x = int(TempX)
                    y = int(TempY)
                    #fail-safe 2
                    if keyboard.is_pressed('ctrl+d'):
                        break
                    keyboard.write(word)
                    print(word)
                #return to begining when at end, thats why its outside of the loop
                SpamText.seek(0)
            for word in SpamText:
                keyboard.write(word)
    except FileNotFoundError:
        NoFile = tk.Label(frame, text = 'Please Select A File', padx=10, pady=5, fg=Modes[mode.get()][2]['text'], bg=Modes[mode.get()][3]['background'])
        NoFile.pack()
acw1668
  • 40,144
  • 5
  • 22
  • 34
richmail
  • 11
  • 6

1 Answers1

2

root.after does not cause a delay. What that says is "please have the main loop call this function later". Your code is going to queue up 5 timer callback requests very quickly, and then continue on. The callbacks will happen later.

When you're coding for a GUI, you have to start thinking about event-driven programming. When you create widgets or call "pack", NOTHING HAPPENS. All that does is queue up a message to be handled later. At some future point, when the mainloop is able to execute, your messages will be popped off and processed. Only then will your visible screen change. That requires a change in the way you program things. You set up your screen, start the mainloop, and then wait for events. Your event callbacks change the state and return, and Tk in the background will update the screen.

Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
  • I want to add a comment about the `while PreferencesStorage['loop']:` that interrupts the `.mainloop()`. – Thingamabobs Nov 07 '21 at 19:04
  • A valid point. While you are reading that file and processing keystrokes, the tkinter main loop is not running and your GUI will be unresponsive. You have to think differently when doing event-driven coding. – Tim Roberts Nov 07 '21 at 19:07
  • How do I change it to event driven programming? What do you mean by even driven programming? And how do I change the typing so that it dose not interfer with the main loop? – richmail Nov 07 '21 at 19:11
  • @richmail its hard to tell since we dont know what you trying to achive and in which envoirment you do that. You would need to provide a [mre]. But a good start could be to search for tkinter **events** and how to use `.after` for a [coroutine](https://stackoverflow.com/questions/63118430/create-a-main-loop-with-tkinter/63118515#63118515) and put your stuff in a function that is called by that coroutine. – Thingamabobs Nov 07 '21 at 19:18