Python countdown clock with GUI [duplicate] - python

This question already has an answer here:
Making a countdown timer with Python and Tkinter?
(1 answer)
Closed 6 years ago.
I'm having problems with a countdown clock that I was making in Python for a Raspberry Pi. I need to have a countdown clock that counts down from 60 minutes. When time runs out it should display a red text "GAME OVER".
I've already made one using TKinter and a for loop for the actual timer but I couldn't find any way to stop the for loop. I gave up on it.
Is there anyone nice enough to maybe write the actual timer and timer stopping part? I'm good enough at python and TKinter to do everything else that I need.

I'd recommend using generators to handle your for loop and will provide a minimal example but on StackOverflow no one is going to "write the actual timer and timer stopping part" (see What topics can I ask here)
Note this is an example I had before this question was posted and thought it would be helpful to you.
import tkinter as tk
def run_timer():
for time in range(60):
label["text"] = time #update GUI here
yield #wait until next() is called on generator
root = tk.Tk()
label = tk.Label()
label.grid()
gen = run_timer() #start generator
def update_timer():
try:
next(gen)
except StopIteration:
pass #don't call root.after since the generator is finished
else:
root.after(1000,update_timer) #1000 ms, 1 second so it actually does a minute instead of an hour
update_timer() #update first time
root.mainloop()
you will still need to figure out for yourself how to implement after_cancel() to stop it and the red "GAME OVER" text.

Related

Breaking Tkinter Loop Without Using after()?

Question written in Python 3.9.7
This is a hypothetical question. I was entertaining this thought for a project of mine before I realized a much easier alternative, but I'm still curious how you might do this, especially since it might improve my understanding of tkinter and while loops.
Say you have something that needs to be run continuously. You can achieve this easily with a while loop, but what if you wanted to break the loop with a button in tkinter?
I'm familiar with the typical solution. Something like this gets the job done by employing the after() method on the root widget:
import tkinter as tk
root = tk.Tk()
runningLoop = False
def loop():
if running:
#do something
root.after(1, loop)
def start:
global running
running = True
def stop:
global running
running = False
startButton = tk.Button(root, text = "filler text", command = start).pack(side = tk.TOP)
stopButton = tk.Button(root, text = "filler text", command = stop).pack(side = tk.TOP)
root.after(1, loop)
root.mainloop()
However, there's always some form of delay as a requisite of the after function that is, at minimum, 1 ms. What if you wanted there to be no delay? What if you wanted to run the loop as quickly as possible until the stop button is pressed, like a while loop without a break condition does until the program is interrupted? That is how while loops work, right? Is there not a way to more smoothly run the loop continuously without the delay and still have a stop button functionality? Would something like that have to invoke threading or parallel programming techniques?
I ask this only because the delay of the after function is not a problem (and some cases, it's a feature) for most answers on how to do something like this out there that I've seen. Any and all help would be appreciated.

Which code does the mainloop() processes infinitely until any event occurs?

To understand my question kindly follow the paragraphs written below:
What code does the mainloop processes infinitely? Like does it read the code of the entire program again and again?
consider the code:
from tkinter import *
window = Tk()
print("lol")
print("Hello World")
window.mainloop()
the output didn't print "Hello World" or "lol" infinite number of times, so the mainloop() doesn't loop the code of the current module.
Now consider this code:
from tkinter import *
print("lol")
window = Tk()
print("Hello World")
while True:
window.update()
Now, even this code executes the same output, so now we can consider the mainloop() loops the code "window.update()" infite number of times, but more efficiently(somehow).
Now the first question arises what does the window.update() function do to update the values in the GUI, does it re-read the code from top to bottom again, or how does the update function update the GUI widget vaules.
The second question is :
I read this article
"Mainloop in Python Tkinter is an infinite loop of the application window which runs forever so that we can see the still screen.
The application window is like a frame that keeps on destroying every microsecond but the main loop keeps on creating a new updated window.
This process of destroying old window screens and creating a new one happens so fast that human eyes don’t even realize it.
Since the process runs infinite time that is why we are able to see the application in front of us and when we close the window then the loop terminates or exits."
Now if this is true then to recreate an updated window the root.mainloop() must read the entire root GUI code again and again entirely or is there another explanation to it.
I have been trying to understand this for the past 6hrs and I have visited every site and I cannot find the solution for the life of me.
Regards,
Rashik
What code does the mainloop processes infinitely? Like does it read the code of the entire program again and again?
No.
Via this function, it calls this C code which has the embedded Tcl interpreter process one event, or wait for Tkinter_busywaitinterval before trying to process another event
Now, even this code executes the same output, so now we can consider the mainloop() loops the code "window.update()" infite number of times, but more efficiently(somehow).
window.update() calls TCL update, which is described to
[...] bring the application “up to date” by entering the event loop repeatedly until all pending events (including idle callbacks) have been processed.
Your infinite loop doesn't have a sleep, so it's spinning your CPU as hard as possible to do practically nothing.
[...] Does it re-read the code from top to bottom again, or how does the update function update the GUI widget vaules.
It certainly doesn't re-read your code. It processes any pending widget updates, which may have happened by running e.g. window.text("...") in e.g. a click callback or an .after() timeout, etc.
I read this article [...]
That article seems wrong and/or at least over-simplifies things.
This simple example clock should clarify how things work:
import time
import tkinter as tk
root = tk.Tk()
text = tk.Label(root)
text.pack()
def tick():
text["text"] = time.ctime() # update `text` widget's content
root.after(1000, tick) # schedule for this function to be called after 1 second
if __name__ == '__main__':
tick() # call the `tick` function once before entering main loop
root.mainloop()

How to make a timer in tkinter? [duplicate]

This question already has answers here:
How can I schedule updates (f/e, to update a clock) in tkinter?
(8 answers)
Closed 2 years ago.
I want to make a timer that starts when i create an instance of a class, and stop the timer when a method is called. Does anyone know how to make one? I've searched up many tutorials but got no idea what they're doing or it just doesn't fit my code. When i use self.frame.destroy() it needs to ignore the timer code so it doesn't get destroyed. The timer should include second and minutes (and milliseconds if possible). Any help will be greatly appreciated, thanks.
from tkinter import *
root = Tk()
class Start:
def __init__ (self, master):
self.master = master
#code
def timer(self):
#start timer
def end(self):
#end timer
root.mainloop()
Edit: The timer should start from 00:00:00 and not an updating clock.
Hope this helps, https://www.geeksforgeeks.org/create-stopwatch-using-python/
It is actually a stopwatch program which includes hour, minute and second, it has three buttons start, stop and reset with their respective functions.

Why does my progress bar work with "print" command and not with tkinter?

I would like to understand why this code:
import time
for i in range(1,11):
print(i)
time.sleep(1)
shows (as it should!) numbers from 1 to 10, each every 1 second, while this code:
from tkinter import *
import time
root = Tk()
for i in range(1,11):
Label(root, text = i).grid(row=0, column=i-1, padx=5, pady =5)
time.sleep(1)
root.mainloop()
waits for 10 seconds, and then displays a window with the 10 numbers (instead of adding them one by one).
I am aware this is a silly question, but I really can't understand! Many Thanks! Alessandro
Most GUI's work differently to what you expect.
They work in an asynchronous way, which means, that you setup your windows and start an event loop.
This event loop will display all widgets, labels, etc, that you set up before calling the event loop and wait for any events (GUI events like mouse or keyboard events, timer events and perhaps network events).
When any event is encountered code associated to that event will be called and this code can request to change the GUI (show or hide elements, change labels or attributes of graphical widgets) However the change to the GUI will only be performed when you give control back to the event loop (when the code handling an event finished)
In your given code you change a label in a for loop with sleep statements, but only after the for loop is finished your main loop is being called and this is the moment, where the final state of your GUI will be displayed.
So what you encounter is a know issue for almost all GUI / asynhronous kind of applications.
You have to rewrite your code such, that you start a timer event, and when the timer event fires a function will set a label and increase the counter by 1. And if the counter is not 11 it will restart another timer
This is because the time.sleep function is before the root.mainloop function.
root.mainloop is what causes the window to appear on-screen and start doing things. Instead, I'd recommend using window.after, as that tells the window to run a function after some time when it's on-screen.
Here's an example of a modification you could make (it's not that good but it works):
from tkinter import *
import time
root = Tk()
progress = 0
end = 10
def update_progress():
global progress
progress += 1
Label(root, text = progress).grid(row=0, column=progress-1, padx=5, pady =5)
if progress < end: root.after(1000,update_progress) # Tell the window to call this function in 1000ms (1 second)
root.after(0,update_progress) # Tell the window to run the update_progress function 0ms after now.
root.mainloop()
I'd recommend looking at gelonida's answer for an explanation of why your original code didn't work, and what you need to keep in mind when programming with GUIs in the future.

Timer in a traffic light simulation [duplicate]

This question already has answers here:
Measuring elapsed time with the Time module
(10 answers)
Closed 6 years ago.
I'm currently working on a Python 3.x project and I'm supposed to make a simple crossroad simulation with traffic lights etc. My only problem right now is that I am not aware of any way to measure time so as to use it to change the traffic lights accordingly. Is there any way to create a virtual timer which will begin as soon as the simulation starts and goes on infinitely until the window is closed? I'm considering using the time or timeit modules, but I'm a bit lost here.
Thanks in advance.
Since you included the tag tkinter, there is a tkinter-specific solution that works quite well. You can use the after method available on every widget to schedule an event to happen in the future.
In the simplest case, you can have a function that will run some other function on a given interval. For example:
import tkinter as tk
def run_periodically(func, ms):
func()
root.after(ms, run_periodically, func, ms)
def tick():
global count
count += 1
tick_label.configure(text="count: %d" % count)
count = 0
root = tk.Tk()
tick_label = tk.Label(root, text="")
tick_label.pack(padx=20, pady=20)
run_periodically(tick, 1000)
root.mainloop()
Of course, instead of having something called on a schedule, you can also just schedule the jobs as needed. For example, when the light turns red you can use after to both turn it off and turn the green on. You can then use after to turn the green off and the yellow on, and so on. Since this sounds like a homework assignment I won't provide an example.

Categories