anthony crimin
anthony crimin

Reputation: 39

break a while loop when threading with argument passing in tkinter

I am trying to break a while loop using tkinter while threading. If I make the log variable global I can break the loop, but I would rather stay away from global variables, any advice would be appreciated`

import tkinter as tk
import threading
import time


def gui_input():

    root = tk.Tk()

    def close_window():
        root.destroy()


    def logging(buttonId):

        global log

        if buttonId == 1:
            log=True
        elif buttonId == 2:
            log=False

        def run():

            while True:            

                print('hello')
                time.sleep(1)

                if log==False:
                    break


        thread = threading.Thread(target=run)
        thread.start()       

    def main():

        # create the GUI
        label = tk.Label(root, text="Balance Table Input:")
        #optionList = ['fixed','simple support','free','concentrated load','distributed load','pin']

        label.grid(column=1,row=1,columnspan=1,sticky='EW')

        submit1 = tk.Button(root,text='Close',command = lambda:close_window())
        submit1.grid(column=3,row=2,columnspan=1,sticky='EW')

        submit2 = tk.Button(root,text='Record',command = lambda:logging(1))
        submit2.grid(column=3,row=5,columnspan=1,sticky='EW')

        submit3 = tk.Button(root,text='Stop Logging',command = lambda:logging(2))
        submit3.grid(column=3,row=8,columnspan=1,sticky='EW')


    main() 
    root.mainloop()

    return()

gui_input()

Upvotes: 0

Views: 635

Answers (1)

Mike - SMT
Mike - SMT

Reputation: 15226

I would rather stay away from global variables.

The best way to avoid global variables IMO is to build a class and use a class attribute to manage the variable. So my example will convert your code to a class.

am trying to break a while loop using tkinter while threading.

Honestly a while loop is most of the time something you want to avoid in Tkinter. Tkinter is event driven so what ends up happening during a while loop is the mainloop() is blocked until the while loop ends. (I know you are using threading for the run() function but its important information to know about tkinter in any case). This can be avoided by using the tkinter method after() with after() we can create a simple loop that checks a value and then does something.

Here is a simplified example using your code:

import tkinter as tk


class Example(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        label = tk.Label(self, text="Balance Table Input:")
        label.grid(column=1, row=1, columnspan=1, sticky='EW')
        submit1 = tk.Button(self, text='Close', command=self.close_window)
        submit1.grid(column=3, row=2, columnspan=1, sticky='EW')
        submit2 = tk.Button(self, text='Record', command=lambda:self.logging(True))
        submit2.grid(column=3, row=5, columnspan=1, sticky='EW')
        submit3 = tk.Button(self, text='Stop Logging', command=lambda:self.logging(False))
        submit3.grid(column=3, row=8, columnspan=1, sticky='EW')
        self.log = True
        self.log_checker()

    def close_window(self):
        self.destroy()

    def log_checker(self):
        if self.log == True:
            print("Hello")            
        self.after(1000, self.log_checker)

    def logging(self, log_tf):
            self.log = log_tf

if __name__ == "__main__":
    Example().mainloop()

Upvotes: 2

Related Questions