1

tl;dr : Why is my GUI crashing when I move it.

Hi, fist of all, yes, I look up some of the similar post here and on google, I might have missed the golden apple so if this question as truly been answered 40 times, then I'm genuinely sorry.

So I'm using Python and my script is basically two loop a small one where you are "stuck" until a key is pressed and a bigger loop that contain all the actual good stuff.

My issue is the GUI, everything works fine-ish, the issue is when you interact with the windows it crashes. I tried to look threading, but I did not manage to make it work as I want it to. And as the script is basically a "while 1:" I can understand that the GUI don't like it...

The GUI itself is just used as an output, buttons aren't needed and I don't need a huge refresh rate on it.

I'm willing to change most of my code if needed, I'm still in early development phase. Especially drop Tkinter, I'm "almost" sure I can do what I want with PyGame, but that seems overkill to me.

The code below is strip of all unnecessary code, just the barebone but if this GUI doesn't crash, it should work for my complete script.

import keyboard as kb
from tkinter import *
# Much more imports are needed for the full script
# Here I also define a lot of fonction use in the loop


def talk(string: str):
    """
    Update the UI witht he new text to output
    :param string: the strind to output
    :return: None
    """
    canvas.create_polygon([0, 0, 0, 125, 600, 125, 600, 0], fill="black", width=2)
    canvas.create_text(300, 100, text=string, font="terminal 20", fill="white")
    canvas.pack()
    root.update()


# Creating the ui
root = Tk()
canvas = Canvas(root, width=600, height=250, background='black')
canvas.create_line(50, 200, 550, 200, fill="red", width=3)
canvas.pack()
root.update()

Stop = False
while not Stop:                     # I do have way to stop this loop and shutdown the script properly
    PushToTalk = False
    talk("")                        # Reseting the output text
    while not PushToTalk:           # Stuck here until "pause" key is press
        if kb.is_pressed("pause"):
            PushToTalk = True

    talk("Yes ?")
    # Here are a lot of stuff happening
    # And the "talk" function is use a lot for upputing informations
print("Bye")

Hope you can Help me !

Lyxilion.

Lyxilion
  • 53
  • 4
  • 1
    First you have to understand, `Tkinter` uses the concept of **event-driven programming**, in which custom-written `callback` functions, receive the flow of control from the `.mainloop()` dispatcher. Read [Is this bad programming practice in tkinter?](https://stackoverflow.com/questions/25454065/is-this-bad-programming-practice-in-tkinter) and [tkinter-understanding-mainloop](https://stackoverflow.com/questions/29158220/tkinter-understanding-mainloop/29158947#29158947) – stovfl Feb 27 '19 at 21:31

1 Answers1

1

As the inner while loop blocks the update of your window, you can add root.update() at the end of the inner while loop as below:

Stop = False
while not Stop:                     # I do have way to stop this loop and shutdown the script properly
    PushToTalk = False
    talk("")                        # Reseting the output text
    while not PushToTalk:           # Stuck here until "pause" key is press
        if kb.is_pressed("pause"):
            PushToTalk = True
        root.update()  # let tkinter handle update    
    talk("Yes ?")
    # Here are a lot of stuff happening
    # And the "talk" function is use a lot for upputing informations
print("Bye")

However it is not a good practice using while loop in main thread. Better put the above code block in a thread:

import keyboard as kb
from tkinter import *
import threading
# Much more imports are needed for the full script
# Here I also define a lot of fonction use in the loop


def talk(string: str):
    """
    Update the UI witht he new text to output
    :param string: the strind to output
    :return: None
    """
    canvas.itemconfig(msg, text=string)


# Creating the ui
root = Tk()
canvas = Canvas(root, width=600, height=250, background='black')
canvas.create_line(50, 200, 550, 200, fill="red", width=3)
msg = canvas.create_text(300, 100, text='welcome', font="terminal 20", fill="white")
canvas.pack()

Stop = False

def chat():
    while not Stop:
        talk("")
        while not kb.is_pressed("pause"): pass
        talk("Yes ?")
        # Here are a lot of stuff happening
        # And the "talk" function is use a lot for upputing informations
    print("Bye")

threading.Thread(target=chat, daemon=True).start()
root.mainloop()
acw1668
  • 40,144
  • 5
  • 22
  • 34