Home > other >  How to break a while loop with a tkinter button without freezeing the executable
How to break a while loop with a tkinter button without freezeing the executable

Time:09-12

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)

CodePudding user response:

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()
  • Related