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.
Related
This question already has answers here:
How do I stop tkinter after function?
(3 answers)
Closed 3 years ago.
I am a beginner in Python and I am trying to create a timer in tkinter. I want to have a button which can stop the timer, however I just can't seem to figure out how to do this. I have tried researching about threads and classes but for such a simple task as a timer do I need these complicated concepts?
import tkinter as tk
from tkinter import *
def countdown(count):
# change text in label
label['text'] = count
if count > 0:
# call countdown again after 1000ms (1s)
root.after(1000, countdown, count-1)
def stop():
# THIS IS THE FUNCTION I WANT TO USE TO STOP THE TIMER, HOWEVER I DO NOT KNOW HOW, RIGHT NOT I HAVE JUST PUT exit() WHICH QUITS THE WHOLE PROGRAM
countdown(exit())
root = tk.Tk()
root.geometry('600x600-200-0')
label = tk.Label(root)
label.place(x=35, y=15)
# call countdown first time
countdown(10)
# root.after(0, countdown, 5)
# Button, pressing it leads to greeting command
button = Button(text="OK", command=stop)
button.pack()
root.mainloop()
I was just wondering if there was a simple solution to this problem, as when I was researching all the tkinter stop timers had such complex code. Thank you in advance!
You just need somewhere to store the job number from the after() function.
job = None
def countdown(count):
# change text in label
label['text'] = count
if count > 0:
global job
# call countdown again after 1000ms (1s)
job = root.after(1000, countdown, count-1)
def stop():
global job
if job:
root.after_cancel(job)
job = None
As title mentions, I'm trying to update the values in my labels in a tkinter gui. The values are taken from OpenWeatherMap API using pyown and at my subscription level, I can only make 60 calls/minute. Since I plan to make many calls, I would like to have my gui update every minute or 5-minutes. I've spent the last few days reading the similar questions and I have figured out that I need the sleep function to delay the update. Some have suggested that I put what I want to repeat in a while True infinite loop, but wheN I tried that, the gui only updated when I closed out the window, and I was unable to control the time in between updates. Others have suggested that I use the .after function, but when I do this, my program compiles but the gui never pops up. I'm looking for someone to show me how either of these solutions work in my code specifically, or if there is a third solution that lends itself better to my code that would be better, please let me see how it would look, because I am stumped.
import tkinter as tk
import pyowm
from datetime import datetime, timedelta
class WeatherInfo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.wm_title('Forecast')
self.currentTime = tk.StringVar(self, value='')
self.d2temp_7 = tk.StringVar(self,value='')
self.owm = pyowm.OWM('*INSERT YOUR OWM KEY HERE*')
self.headLabel = tk.Label(self, text='5-Day Forecast of Cayce, US.')
self.headLabel.pack()
self.footLabel = tk.Label(self, textvariable=self.currentTime)
self.footLabel.pack(side=tk.BOTTOM)
self.day2Frame = tk.LabelFrame(self, text='D2')
self.day2Frame.pack(fill='both', expand='yes', side=tk.LEFT)
tk.Label(self.day2Frame, text="Temperature:").pack()
tk.Label(self.day2Frame, textvariable=self.d2temp_7).pack()
self.search()
def search(self):
fc = self.owm.three_hours_forecast_at_id(4573888)
try:
self.currentTime.set(datetime.today())
self.d2temp_7.set("7am: " + str(fc.get_weather_at((datetime.today().replace(hour=13, minute=00) + timedelta(days=1))
.strftime ('%Y-%m-%d %H:%M:%S+00')).get_temperature('fahrenheit')['temp']))
except:
self.temp.set('Pick a city to display weather.')
def _quit(self):
self.quit()
self.destroy()
if __name__== "__main__":
app = WeatherInfo()
app.mainloop()
More on what I have tried:
while True:
def __init__
def search
But as this answer points out, other answer , I won't see any changes I make in my while True preceding the root.mainloop()
This question came close to my answer using root.after(milliseconds,results), but when I implimented this answer my gui never showed. infinitely update
Thank you to anyone who tries to answer this.
Edit: I have made my code shorter as per recommendation.
Based on this you can have a function,forecast_update, like the following:
import tkinter as tk
#these two needed only for API update simulation
import random
import string
root = tk.Tk()
forecast = tk.Label(text="Forecast will be updated in 60 seconds...")
forecast.pack()
# returns a string with 7 random characters, each time it is called, in order to simulate API
def update_request_from_api():
return ''.join(random.choice(string.ascii_lowercase) for x in range(7))
# Your function to update the label
def forecast_update():
forecast.configure(text=update_request_from_api())
forecast.after(60000, forecast_update) # 60000 ms = 1 minute
# calling the update function once
forecast_update()
root.mainloop()
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.
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.
My program is doing complex calculation that last for around 30 minutes. I would like to be updated about the values of some variables in a Tkinter GUI with ideally certain variables linked to certain labels so that they update automatically whenever they change their values. While I understand that I could create 2 threads (one for the main program and one for TKinter that calls itself every second or so), I'm wondering if there's a more elegant way to handle this. Any suggestions are appreciated.
The below example shows how it could possibly look like, but the example doesn't work.
import Tkinter as tk
import time
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.counter = tk.Label(self, text="")
self.counter.pack()
# start the clock "ticking"
self.mainLoop()
def mainLoop(self):
for i in range (10000):
j=i^2
self.counter.configure(text=str(j))
time.sleep(0.1)
if __name__== "__main__":
app = SampleApp()
app.mainloop()
However, it does work when the mainLoop is replaced with this:
def mainLoop(self):
now = time.strftime("%H:%M:%S" , time.gmtime())
self.counter.configure(text=now)
# call this function again in one second
self.after(1000, self.mainLoop)
My questions:
Why does it work with "self.after" but not with a for loop
Is there a more elegant way to update labels event driven (not based on a button, but on a calculation that changes certain variables)
To answer first question -
Why does it work with "self.after" but not with a for loop
The __init__() method of a class is called when an object of that class in created. Now in your case, the class gets created in line -
app = SampleApp()
And in your __init__() , you call - self.mainLoop() .
In your for loop case, all this is running in the main thread. And so it would not return from the self.mainLoop() untill it has completed, since you are not start self.mainLoop() as a separate thread, you are doing that in the same thread. Hence, the control would reach the root.mainloop() line only after self.mainLoop()` has completed and returned the control back.
In case of using after() method, it behaves something like it registers an event to be fired after some amount of time, and immediately returns, it does not wait for that much amount of time and neither for the function to return. Hence the control immediately gets returned and it calls root.mainloop() to show the GUI.