0

I've tried by now several methods found online but I can't seem to find a solution. What I want to create is to enable a while loop with a button and disable it with another button. The main issue, is that while the loop is active, it freezes my GUI when I press my "disable" button. The while loop does stop, but I have to kill the executable in task manager and restart it in order to re-enable the while loop.

Code:

from tkinter import *
import time

top = Tk()
top.title("Corsair")
top.geometry('100x100')
top.resizable(False, False)

def b1(): 
    while True:
        [MY MAIN CODE]
#       if But2.is_pressed:
#           break

but1 = Button(top, image = onbutton, text ="On", command = b1)
but2 = Button(top, image = offbutton, text ="Off", pady = 100, padx = 10, command = top.destroy)

but1.pack()
but2.pack()
top.mainloop()

I've tried; if But2.is_pressed to break the code, which freezes the GUI.

Make but2 to destroy top window, which freezes the GUI.

I've tried ;

x = 1

def b1(): 
    while True:
        if x == 1:
            [MY MAIN CODE]
        else:
            break   

def b2():
    x = 0   

but1 = Button(top, image = onbutton, text ="On", command = b1)
but2 = Button(top, image = offbutton, text ="Off", pady = 100, padx = 10, command = b2)
but3 = Button(top, text ="Exit", pady = 100, padx = 20, command = top.destroy)
6
  • 2
    This is not how tkinter is designed to be used. Please look at event driven programming. You shouldn't use while True loops in tkinter code. Commented Sep 11, 2022 at 12:08
  • Thanks! Guess it's then either freezing the GUI and manual kill the exe or avoid the entire thing all together then? Commented Sep 11, 2022 at 13:39
  • It's just that you are using tkinter incorrectly. Look at some tkinter tutorials. Commented Sep 11, 2022 at 13:44
  • this question has been asked before: stackoverflow.com/questions/53580507/… Commented Sep 11, 2022 at 14:28
  • Does this answer your question? Disable / Enable Button in TKinter Commented Sep 11, 2022 at 14:28

1 Answer 1

0

This problem was few times on Stackoverflow:

If you run long-running loop then you should run it in separate thread.

But if every loop is not so long then you could use .after(milliseconds, function_name) at the end of function (instead of while and sleep) to repeat function again - and this will work as loop, and tkinter will have time to run own mainloop

import tkinter as tk  # PEP8: `import *` is not preferred
import time

# --- functions ---  # PEP8: all functions before main code

def b1(): 
    print('MY MAIN CODE')
    if running:
        # repeat after 100ms (0.1s)
        top.after(100, b1)  # funcion's name without ()
    else:
        print('STOP')

def b2(): 
    global running
    
    running = False
    
# --- main ---

running = True

top = tk.Tk()

but1 = tk.Button(top, text="On",  command=b1)   # PEP8: inside `()` use `=` without spaces
but2 = tk.Button(top, text="Off", command=b2)
but1.pack()
but2.pack()

top.mainloop()

EDIT:

If you want to use button On to restart loop again then it may need extra function to set again running = True

import tkinter as tk  # PEP8: `import *` is not preferred
import time

# --- functions ---  # PEP8: all functions before main code

def b1():
    global running

    running = True
    
    loop()
    
def loop():    
    print('MY MAIN CODE')
    
    if running:
        # repeat after 100ms (0.1s)
        top.after(100, loop)  # funcion's name without ()
    else:
        print('STOP')
        
def b2(): 
    global running
    
    running = False
    
# --- main ---

running = True

top = tk.Tk()

but1 = tk.Button(top, text="On",  command=b1)   # PEP8: inside `()` use `=` without spaces
but2 = tk.Button(top, text="Off", command=b2)
but1.pack()
but2.pack()

top.mainloop()
Sign up to request clarification or add additional context in comments.

3 Comments

Awesome! Many thanks! That did the trick! Now the GUI doesn't freeze anymore (well only for a second or two, but I can live with that haha). And many thanks for your additional comments on the code itself! Sure is helpful! Been a bit rusty in Python and sure need to revisit a tutorial or two at least.
If loop runs longer-running code then you may add few top.update() between lines - and this will force tkinter to get key/mouse events from system, sendt them to widgets and (re)draw widgets in window.
Sorry a bit late, haven't been logged in for a while. Many thanks! I'll try that out as well and see if it gives the desired effect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.