Home > Back-end >  while loop/thread problem with stopwatch program
while loop/thread problem with stopwatch program

Time:12-18

So I am making a stopwatch program with tkinter.

At the moment, I am in the process of implementing a stop button for the stopwatch.

I can start the stopwatch and it will update the Label fine but my end button isn't working and I can't seem to figure out why.

Here's my code so far:

from tkinter import *
from time import sleep
import threading

root = Tk()
root.title("Clock")


class Buttons:

    def __init__(self, master):

        self.menu = Menu(master)
        master.config(menu=self.menu)

        self.menu.add_command(label="Stopwatch")
        self.menu.add_command(label="Timer")
        self.menu.add_command(label="Quit", command=quit)

        self.stopwatchStart = Button(master, text="Start", command=self.test_start)
        self.stopwatchStart.config(height=2, width=5)
        self.stopwatchStart.grid(row=0)

        self.stopwatchEnd = Button(master, text="End", command=self.stopwatch_End)
        self.stopwatchEnd.config(height=2, width=5)
        self.stopwatchEnd.grid(row=1)

        self.labelSeconds = Label(master, text="Seconds:")
        self.labelSeconds.grid(row=0, column=1)
        self.stopwatchSeconds = Label(master, text="0")
        self.stopwatchSeconds.grid(row=0, column=2)

    def test_start(self):  
        print("Starting thread")
        t = threading.Thread(target=self.stopwatch_Start)
        t.setDaemon(True)
        t.start()

    def stopwatch_Start(self, test=False):
        print("Stopwatch started")
        stopwatch_seconds = "0"
        stopwatchBreak = test
        print(f"stopwatchBreak == {stopwatchBreak}")
        while not stopwatchBreak:
            print(stopwatch_seconds)
            stopwatch_seconds = int(stopwatch_seconds)
            stopwatch_seconds  = 1
            self.stopwatchSeconds.config(text=stopwatch_seconds)
            root.update()
            sleep(1)
        print("Stopping stopwatch")
        return

    def stopwatch_End(self):
        Buttons.stopwatch_Start(self, True)
        print("Attempting to end")


b = Buttons(root)
root.mainloop()

I am using threading to run the stop watch and the window from tkinter at the same time by the way.

Also I have put several print() across the functions to see what is succeeding and what isn't. I think the problem may have something to do with the thread in test_start(). The loop that won't end when I click the end button is in stopwatch_Start(). It just keeps counting up.

I have received no error messages

Does anyone have any suggestions/alternatives to stopping the stopwatch?

CodePudding user response:

look at this code

    def stopwatch_End(self):
        Buttons.stopwatch_Start(self, True)
        print("Attempting to end")

this is your problem =>

    Buttons.stopwatch_Start(self, True)

correct this with:

self.stopwatch_Start(True)

here you are call "stopwatch" on the class Buttons, this is an unbound function!!! "Buttons.stopwatch" is different than "self.stopwatch" the later is bound to the instance.

from tkinter import *
from time import sleep
from threading import Thread
from threading import Event

root = Tk()
root.title("Clock")


class Buttons:

    def __init__(self, master):
        self.evt = Event()
        self.menu = Menu(master)
        master.config(menu=self.menu)

        self.menu.add_command(label="Stopwatch")
        self.menu.add_command(label="Timer")
        self.menu.add_command(label="Quit", command=quit)

        self.stopwatchStart = Button(master, text="Start", command=self.test_start)
        self.stopwatchStart.config(height=2, width=5)
        self.stopwatchStart.grid(row=0)

        self.stopwatchEnd = Button(master, text="End", command=self.stopwatch_End)
        self.stopwatchEnd.config(height=2, width=5)
        self.stopwatchEnd.grid(row=1)

        self.labelSeconds = Label(master, text="Seconds:")
        self.labelSeconds.grid(row=0, column=1)
        self.stopwatchSeconds = Label(master, text="0")
        self.stopwatchSeconds.grid(row=0, column=2)

    def test_start(self):  
        print("Starting thread")
        t = Thread(target=self.stopwatch_Start)
        t.setDaemon(True)
        t.start()

    def stopwatch_Start(self, test=False):
        print("Stopwatch started")
        stopwatch_seconds = "0"
        stopwatchBreak = test
        print(f"stopwatchBreak == {stopwatchBreak}")
        # self.evt.is_set() will force the loop to check its actually state if it True or not
        while not self.evt.is_set():
            print(stopwatch_seconds)
            stopwatch_seconds = int(stopwatch_seconds)
            stopwatch_seconds  = 1
            self.stopwatchSeconds.config(text=stopwatch_seconds)
            root.update()
            sleep(1)
        print("Stopping stopwatch")
        return

    def stopwatch_End(self):
        #we set self.evt to True so that the while loop will be broken
        self.evt.set()
        print("Attempting to end")


b = Buttons(root)
root.mainloop()
  • Related