3
\$\begingroup\$

As part of a personal project, I wanted to make a stopwatch with Python. I wish to show my friend but at the moment it is a little messy and long. Is there any way to make it more compact or easier to read?

    #stopwatch

from tkinter import*
import time

root=Tk()
root.configure(background=("black"))
root.title("stopwatch")
root.geometry("1000x800")
time_elapsed1=0
time_elapsed2=0
time_elapsed3=0
i=0
j=0
time1=0

def create_label(text,_x,_y):
    label = Label(root, text=text,fg='white', bg="black",font=("default",10,"bold"))
    label.place(x=_x,y=_y,width=100,height=45)
def start():
    start_button.place_forget()
    stop_button.place(x = 20, y = 300, width=300, height=100)
    global time_elapsed1,time_elapsed2,time_elapsed3,time1,self_job,time2
    time2=int(time.time())
    if time2!=time1:
        time1=time2
        if time_elapsed1<59:
            time_elapsed1+=1
            clock_frame.config(text=str(time_elapsed3) + ":" + str(time_elapsed2)+ ":" + str(time_elapsed1))
        else:
            time_elapsed1=0
            if time_elapsed2<59:
                time_elapsed2+=1
                clock_frame.config(text=(str(time_elapsed3) + ":" + str(time_elapsed2)+ ":" + str(time_elapsed1)))
            else:
                time_elapsed2=0
                if time_elapsed3<23:
                    time_elapsed3+=1
                    clock_frame.config(text=(str(time_elapsed3) + ":" + str(time_elapsed2)+ ":" + str(time_elapsed1)))
                else:
                    print("you left it on for too long")
    self_job=root.after(1000,start)

def stop():
    global self_job
    if self_job is not None:
        root.after_cancel(self_job)
        self_job = None
    stop_button.place_forget()
    start_button.place(x = 20, y = 300, width=300, height=100)

def clear():
    global time_elapsed1,time_elapsed2,time_elapsed3,time1,self_job,time2,label,i,j
    try:
        stop()
    except:
        start()
        stop()
    clock_frame.config(text="0:0:0")
    time_elapsed1=0
    time_elapsed2=0
    time_elapsed3=0
    time_1=0
    time_2=0
    i=0
    j=0
    wig=root.winfo_children()
    for b in wig:
        b.place_forget()
    start_button.place(x = 20, y = 300, width=300, height=100)
    lap_button.place(x = 660, y = 300, width=300, height=100)
    reset_button.place(x = 340, y = 300, width=300, height=100)
    clock_frame.place(x = 200, y = 50, width=600, height=200)


def lap():
    global time_elapsed1,time_elapsed2,time_elapsed3,time1,self_job,time2,i,j
    if i<9:
        create_label((str(time_elapsed3)+":"+str(time_elapsed2)+ ":" + str(time_elapsed1)),20+(110*i),400+(j*50))
    else:
        j+=1
        i=0
        create_label((str(time_elapsed3)+":"+str(time_elapsed2)+ ":" + str(time_elapsed1)),20+(110*i),400+(j*50))
    i+=1





clock_frame=Label(text="0:0:0",bg="black",fg="blue",font=("default",100,"bold"))
start_button=Button(text="START",bg="green",fg="black",command=start,font=("default",50,"bold"))
stop_button=Button(text="STOP",bg="red",fg="black",command=stop,font=("default",50,"bold"))
lap_button=Button(text="LAP",bg="#4286f4",fg="black",command=lap,font=("default",50,"bold"))
reset_button=Button(text="RESET",bg="orange",fg="black",command=clear,font=("default",50,"bold"))


start_button.place(x = 20, y = 300, width=300, height=100)
lap_button.place(x = 660, y = 300, width=300, height=100)
reset_button.place(x = 340, y = 300, width=300, height=100)
clock_frame.place(x = 200, y = 50, width=600, height=200)


root.mainloop()
\$\endgroup\$
3
  • \$\begingroup\$ Welcome to Code Review! Self answers are welcome here, too: things to consider include the Style Guide for Python Code. \$\endgroup\$
    – greybeard
    Mar 25, 2019 at 7:23
  • \$\begingroup\$ Thanks, greybeard-will look into it \$\endgroup\$ Mar 25, 2019 at 14:15
  • \$\begingroup\$ Can you add comments to the code you posted? It is a little hard to understand what each function or if/else block is doing. You will be more likely to get answers if you make it easy to understand what you need. \$\endgroup\$ Mar 25, 2019 at 16:58

1 Answer 1

2
\$\begingroup\$

Have you learned how to make objects in Python? Typically when you have a GUI, you want to have a class in charge of displaying all the GUI pieces, and it has reference to an object such as a Stopwatch that takes care of all of the logic. Stopwatch class would look something like this:

import time

class Stopwatch:
    def __init__(self):
        self.start_time = 0
        self.laps = []

    def start(self):
        # Implement your starting of the timer code here
        self.start_time = time.time()

    def lap(self):
        # Implement your lapping logic
        lap = time.time()
        self.laps.appen(lap)

    def stop(self):
        # Implement your stop timer logic
        elapsed = time.time() - self.start_time

    def reset(self):
        # Implement your watch reset logic here
        self.start_time = 0

    def display_time(self):
        # Return the time to display on the GUI
        elapsed = time.time() - self.start_time
        # Figure out how to break the time into hour:minute:second
        # The time class might even have convenience functions for this sort of thing, look up the documentation
        display = elapsed   # after you made it look nice
        return display

Then in the GUI code you can make a Stopwatch object and let it take care of the messy work of saving times and doing math with them. The GUI class is just concerned with showing stuff the right way. Might look something like (minus positioning all the GUI components):

# GUI
root = Tk()
root.configure(background=("black"))
root.title("stopwatch")
root.geometry("1000x800")

stopwatch = Stopwatch()

def create_label(text,_x,_y):
    label = Label(root, text=text,fg='white', bg="black",font=("default",10,"bold"))
    label.place(x=_x,y=_y,width=100,height=45)

def setup():
    pass
    # Create all of the GUI components and build all the visuals

def start():
    stopwatch.start()   # let it do the logical work
    # do your GUI updates
    create_label(stopwatch.display_time())
    stop_button.place() 

def stop():
    stopwatch.stop() # Logic and math here
    # Do GUI updates for stop
    create_label(stopwatch.display_time())

def clear():
    stopwatch.reset()  # Logic again handled in the Stopwatch class
    # Clean up GUI components

def lap():
    # The Stopwatch class can keep a list of all lap times and make your life easier
    stopwatch.lap()  
    # Next update the GUI
    create_label(stopwatch.display_time())

# Good form to have all the logic run inside functions 
#instead of hanging around to be accidentally executed
if __name__ == "__main__":
    setup()
    root.mainloop()

It will clean up your code and make it easier for you to make changes. The sooner you can learn how to use Objects, the easier your life will become, no matter the language! I leave it up to you to Google the best tutorials on Python objects.

Finally, if you are confused on where Stopwatch class should go, best practice would be to create a file called "stopwatch.py" and paste the Stopwatch class in that file. Then in your main file that is running the code, import that stopwatch by calling from stopwatch import Stopwatch. As long as the stopwatch.py file is right next to your main file, it should be able to import it.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.