Nuh Yamin
Nuh Yamin

Reputation: 353

how to prevent tkinter from freezing when I click somewhere else?

My tkinter gui starts to freeze when I click on somewhere else. Is there a way to prevent that?

Here's my code:

#=========================
from tkinter import *
from time import sleep
import random

#=====================
root=Tk()
root.title("Wise Words")
root.geometry("500x180+360+30")
root.resizable(0,0)
root.call("wm", "attributes", ".", "-topmost", "1")

#===================
def display(random):
    if random == 1:
        return "Be wise today so you don't cry tomorrow"
    elif random == 2:
        return "Frustration is the result of failed expectations"
    elif random == 3:
        return "Wishes are possibilities. Dare to make a wish"
    if True:
        sleep(4)
        r=random.randint(1,3)
        sentence=display(r)
        label.configure(text=str(sentence))
        label.update_idletasks()

    root.after(5000, display(random))

#==================
def Click(event):
    display(random)

#====================== 
label=Button(root, fg="white", bg="blue", text="Click to start!",
    font=("Tahoma", 20, "bold"), width=40, height=4,
    wraplength=400)
label.bind("<Button-1>", Click)
label.pack()

#================
root.mainloop()

Note: The label for display is the Button itself, so I name it 'label'.

Upvotes: 0

Views: 916

Answers (1)

TigerhawkT3
TigerhawkT3

Reputation: 49330

You're doing several strange things in your code:

  • Using time.sleep in a Tkinter application
  • Calling the button a label (there is a Label Tkinter widget)
  • Binding the left mouse button to a button instead of just giving the button a command
  • Passing the random module around and expecting it to evaluate to an integer
  • Returning strings to a button
  • Using an unconditional branching statement (if True:)
  • Masking a module name with a parameter name
  • Expecting the name random to refer to both the random module and a passed argument, at the same time
  • Making a recursive call in a function that already calls after
  • Leaving the button bound to a function that already schedules calls to itself with after, allowing you to schedule many calls
  • Using an if structure to choose a random string instead of using random.choice
  • Scheduling an after call with the result of a function call (display(random)) instead of the function itself

That's not necessarily a complete list.

The following fixes the above issues.

from tkinter import *
import random

def display():
    strings = ("Be wise today so you don't cry tomorrow",
               "Frustration is the result of failed expectations",
               "Wishes are possibilities. Dare to make a wish")
    button.config(text=random.choice(strings))

    root.after(5000, display)

def click(event=None):
    button.config(command='')
    display()

root=Tk()
root.title("Wise Words")
root.geometry("500x180+360+30")
root.resizable(0,0)
root.call("wm", "attributes", ".", "-topmost", "1")
button = Button(root, fg="white", bg="blue", text="Click to start!",
    font=("Tahoma", 20, "bold"), width=40, height=4,
    wraplength=400, command=click)
button.pack()

root.mainloop()

Upvotes: 4

Related Questions