Home > Enterprise >  stoping infinite loop function using another button
stoping infinite loop function using another button

Time:01-31

I am writing a function which should return two other functions in it until I decide to stop it. Maybe I even want the function to run 5 hours. I write my code, and it runs perfectly except for one problem: when I click on the starting button, the button stays pressed and I cannot close the infinite loop. I want a way to stop my program without doing key-interrupting or something else. I think a button which can stop my started process would be fine.

Here is my button:

self.dugme1 = Button(text="Start ", command=self.start, fg="black", bg="green", font="bold")
self.dugme1.place(relx=0.05, rely=0.65)

Here are my functions:

def greeting(self):
    print("hello")


def byee (self):
    print("bye")


def start(self):
    
    while True:
        self.greeting()
        self.byee()

When I click the button these will be run in the terminal infinitely until I stop them using keyboard interrupting. Is there any way to stop it using an elegant way such as a stop button?

CodePudding user response:

You can achieve this with threading. The following code demonstrates a start/stop button for an infinitely running process:

import tkinter as tk
import threading

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.stop_event = threading.Event()
        self.thread = threading.Thread(target = self.start, args = (self.stop_event,))
        self.btn = tk.Button(self, text = "Start", command = self.start_cmd)
        self.btn.pack()
    def start_cmd(self):
        self.btn.config(text = "Stop", command = self.stop_cmd)
        self.thread.start()
    def stop_cmd(self):
        self.stop_event.set()
        self.destroy()
    def start(self, stop_event):
        while not stop_event.is_set():
            self.greeting()
            self.byee()
    def greeting(self):
        print("hello")
    def byee(self):
        print("bye")

app = App()
app.mainloop()

CodePudding user response:

You can use threading on start function. I am sure you'll find more information about this here on over the internet.

Example below:

import threading

self.dugme1 = Button(text="Start ",
                     command=lambda e: threading.Thread(name='start', target=self.start, daemon=True).start(),
                     fg="black",
                     bg="green",
                     font="bold"
                     )

then you can have your start function as:

def start(self):
    if self.start_running == False:
        self.start_running = True
        while self.start_running:
            self.greeting()
            self.byee()

where self.start_running is a variable that is initially set to false at the beginning of your program (or you can set declare it first in start function with a try-except block)

the first if avoids multiple calls to the same button, calling the function more than once.

You can turn "false" the variable self.start_running to stop the execution of start function.

We want the thread to be daemon, so that the function is terminated whenever main terminates. If you don't want those function to exit abruptly, turn daemon=False, but make sure to signal self.start_running=False, before your program exits.

  • Related