How to change countdown to hour/minutes/seconds - python

I am new to Tkinter so im just trying to learn as much as possible. I want to try and make an alarm clock but now im stuck on the time format. This is the current code:
from tkinter import *
teer = Tk()
field = Canvas(teer, bd=0, highlightthickness=0, height='190', width='400', bg='#111111')
field.pack()
def start_countdown(count):
coin = 0.5
teer.resizable(False,False)
counter = Label(teer, fg = "#287aff", bg='#232323', font = ("Lato", 35, "bold"), width='15')
counter.place(x=50, y=50)
counter["text"] = count
if count > 0:
teer.after(1000, start_countdown, count -1)
if count < 500:
coin = 0.6
if count < 300:
coin = 0.7
start_countdown(500)
teer.mainloop()
now what i've been trying to do is chop the 500 (seconds) up into minutes / seconds. Or ultimately change it to hours / minutes / seconds if i may choose to insert an int larger than 3600 into the function. I just want the time hardcoded so i thought it wouldn't be such a problem.
What i tried:
-Experimented with different alarms / countdowns that people made (sadly there aren't many out there that count down instead of up and are also in hours/minutes/seconds.
-Experimented with the format (for example) %H:%M:%S
I Just don't seem to get it.
Would appreciate any help or advice about making a GUI-program that counts down.

You can use divmod to calculate the remaining time.
import tkinter as tk
root = tk.Tk()
a = tk.Label(root,text="")
a.pack()
def set_idle_timer(t):
hours, remainder = divmod(t, 3600)
mins, secs = divmod(remainder, 60)
timeformat = "{:02d}:{:02d}:{:02d}".format(hours, mins, secs)
a.config(text=timeformat)
t -=1
root.after(1000,lambda: set_idle_timer(t))
set_idle_timer(3605)
root.mainloop()

Related

stop the clock within the time limit in tkinter python

I want to stop clock within the time limit, here i have given 5 seconds but the clock is not stopping, kindly help.
import tkinter as tk
from tkinter.constants import *
def start():
global hours, minutes, seconds
if hours == 4:
return
seconds -= 1
if seconds == 00:
minutes -= 1
seconds = 60
if minutes == 00 and seconds == 00:
hours = hours+1
clock.config(text=f'{hours:02}:{minutes:02}:{seconds:02}')
root.after(1000, start)
root=tk.Tk()
clock = tk.Label(root, font=("bold",20), anchor=CENTER, text="00:00:00")
clock.place(relx=0.5, rely=0.5, anchor=CENTER)
hours,minutes,seconds = 0,0,5
start()
root.mainloop()
Just add the variable stop and if stop == True then the clock will stop
Solution to your Question
import tkinter as tk
from tkinter.constants import *
def start():
global hours, minutes, seconds, stop
if hours == 4:
return
if stop == False:
seconds -= 1
if seconds == 00:
stop = True
elif seconds == 00 and minutes != 00 and hours != 00:
minutes -= 1
seconds = 60
elif minutes == 00 and seconds == 00:
hours = hours+1
clock.config(text=f'{hours:02}:{minutes:02}:{seconds:02}')
root.after(1000, start)
root=tk.Tk()
clock = tk.Label(root, font=("bold",20), anchor=CENTER, text="00:00:00")
clock.place(relx=0.5, rely=0.5, anchor=CENTER)
hours,minutes,seconds,stop = 0,0,5, False
start()
root.mainloop()
a Complete clock down counter BONUS
import tkinter as tk
from tkinter.constants import *
def start():
global hours, minutes, seconds, stop
if hours == 4:
return
if stop == False:
seconds -= 1
if seconds == 00 and minutes == 00 and hours == 00:
stop = True
elif seconds == -1 and minutes != 00:
minutes -= 1
seconds = 59
elif hours != 00 and minutes == 00 and seconds == -1:
hours -= 1
minutes = 59
seconds = 59
clock.config(text=f'{hours:02}:{minutes:02}:{seconds:02}')
root.after(1000, start)
root=tk.Tk()
clock = tk.Label(root, font=("bold",20), anchor=CENTER, text="00:00:00")
clock.place(relx=0.5, rely=0.5, anchor=CENTER)
hours,minutes,seconds,stop = 0,0,5, False
start()
root.mainloop()
Solution without that many if conditions. I use a timestamp, but I have also some trouble with the timezone I think. Maybe someone can solve my offsets.
My tkinter TIMER app, with bell:
import tkinter as tk
import calendar
from datetime import datetime
import time
import sys
class Countdown(tk.Frame):
def __init__(self,master):
tk.Frame.__init__(self, master)
global target
self.master = master
self.clock = tk.Label(text="00:00:00", fg="Green", font=("bold",40))
self.clock.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
timestamp = calendar.timegm(time.localtime())
print("Timestamp",timestamp)
print("Timestamp_future",timestamp + t_plus)
target = timestamp + t_plus
self.update_clock()
def update_clock(self):
current = calendar.timegm(time.localtime()) -23*3600
countdown = target - current
self.down_time = datetime.fromtimestamp(countdown).strftime("%H:%M:%S")
self.clock.configure(text=self.down_time)
if countdown/3600 != 23:
self.after(1000, self.update_clock)
else:
print('\a', end='', flush=True)
root = tk.Tk()
global t_plus
######### SET YOUR TIME FOR THE COUNTDOWN ############
your_timer_set = '00:00:05' # hours, minutes, seconds
######################################################
countdown = time.strptime(your_timer_set, '%H:%M:%S')
hours = int(countdown.tm_hour)
minutes = int(countdown.tm_min)
seconds = int(countdown.tm_sec)
t_plus = ((hours*3600)+(minutes*60)+seconds)
print("SET_TIME",t_plus)
app=Countdown(root)
root.title("Countdown")
root.geometry("400x400+400+150")
root.mainloop()

Tkinter lag at the "update" command

I made a timer just to test something out. and for some reason it starts lagging, here is the timer:
from tkinter import *
from time import sleep
main = Tk()
main.title("Timer")
c = Canvas(main,width=1000,height=400)
c.pack()
c.config(bg="black")
hours = -1
while True:
hours += 1
for minutes in range(60):
for seconds in range(60):
c.create_rectangle(0,0,1000,400,fill="black")
c.create_text(500,200,text=(str(hours)+":"+str(minutes)+":"+str(seconds)),font=("",200),fill="white")
c.update()
sleep(1)
Can someone figure out where it happens? I noticed I can run the timer without tkinter and just with print, but I need to use tkinter for other projects too.
You are creating text widgets covered by black rectangles in succession, without ever removing them - in essence, every second, you are piling two more canvas items on top of all the previous ones!
The correct approach is to use the tkinter.mainloop in conjunction with the tkinter.after method, and steer clear from using a while loop, and tkinter.update. You can change the text displayed by a canvas text item using itemconfigure.
The use of time.sleep in a GUI is a recipe to have your GUI stop responding to interactions - don't do that!
Maybe do this instead:
import tkinter as tk
def update_clock():
clock_text = f'{hours}:{str(minutes).zfill(2)}:{str(seconds).zfill(2)}'
canvas.itemconfigure(clock, text=clock_text)
main.after(1000, _increment_time)
def _increment_time():
global clock, hours, minutes, seconds
seconds += 1
if seconds == 60:
seconds = 0
minutes += 1
if minutes == 60:
minutes = 0
hours += 1
update_clock()
main = tk.Tk()
main.title('Timer')
canvas = tk.Canvas(main, width=1000, height=400, bg='black')
canvas.pack()
hours, minutes, seconds = 0, 0, 0
clock = canvas.create_text(500, 200, font=('', 200), fill='white')
update_clock()
main.mainloop()

Clunky/slow dragging functionality on my analog clock project

I just finished my first Python project, an analog clock. I managed to reach a state where I implemented everything I had in mind and fixed the issues that followed. The last thing I added in is a dragging capability for my clock and while it works it seems slow or at least just unsmooth. Right now I lack the knowledge and experience to understand why its happening and let alone fix it.. Any help or ideas would be appreciated, Thanks in advance. :)
Here is my code:
# Imported tkinter for its methods
import tkinter as tk
# Imported turtle for drawing the clock's hands
import turtle
# Imported time to handle setting and updating the time
import time
# Declared and set the color used for transparency
transparent_clr = '#FB00FF'
# Setup a borderless window with transparent background
# and always on top flag
root = tk.Tk()
root.overrideredirect(True)
root.wm_attributes('-topmost', 1)
root.deiconify()
root.attributes('-transparentcolor', transparent_clr)
# Setup the clock's face using an image
Clock_bg = tk.PhotoImage(file='Clock_bg.png')
canvas = tk.Canvas(width=300, height=300, highlightthickness=0)
screen = turtle.TurtleScreen(canvas)
canvas.create_image(0, 0, image=Clock_bg)
canvas.pack()
screen.tracer(0)
screen.bgcolor(transparent_clr)
# Configure the pen used for the clock's hands
draw = turtle.RawTurtle(screen)
draw.hideturtle()
draw.speed(0)
draw.pensize(3)
# Retain Windows TaskBar visibility and function such as exiting
# the app
wn = tk.Toplevel(root)
wn.iconify()
wn.iconbitmap('Clock_icon.ico')
wn.attributes('-alpha', 0.0)
def wn_destroy():
wn.protocol('WM_DELETE_WINDOW', exit_func)
def exit_func():
root.destroy()
wn_destroy()
# Make the clock draggable
def draggable():
root._offsetx = 0
root._offsety = 0
root.bind('<Button-1>', winclick)
root.bind('<B1-Motion>', windrag)
def windrag(event):
x = root.winfo_pointerx() - root._offsetx
y = root.winfo_pointery() - root._offsety
root.geometry('+{x}+{y}'.format(x=x, y=y))
def winclick(event):
root._offsetx = event.x
root._offsety = event.y
draggable()
# Draw the clock and its hands
def draw_clock(h, m, s, draw):
# Draw the hours hand
draw.penup()
draw.goto(0, 0)
draw.color('black')
draw.setheading(90)
angle = (h / 12) * 360 + (m / 60) * 30
draw.rt(angle)
draw.pendown()
draw.fd(70)
# Draw the minutes hand
draw.penup()
draw.goto(0, 0)
draw.color('black')
draw.setheading(90)
angle = (m / 60) * 360 + (s / 60) * 6
draw.rt(angle)
draw.pendown()
draw.fd(100)
# Draw the seconds hand
draw.penup()
draw.goto(0, 0)
draw.color('red')
draw.setheading(90)
angle = (s / 60) * 360
draw.rt(angle)
draw.pendown()
draw.fd(60)
# Update the time in real time
while True:
# Declared and set the hour, minutes and seconds
h = int(time.strftime('%I'))
m = int(time.strftime('%M'))
s = int(time.strftime('%S'))
draw_clock(h, m, s, draw)
screen.update()
time.sleep(1)
draw.clear()
"You are using your own mainloop with time.sleep(1), therefore root.geometry( gets only called every second. –stovfl"
Thanks a billion, stovf1!

Having issues getting a Scene to redraw

I recently started learning Python and just finished my courses on it on CodeAcademy, so I've been trying to come up with small projects to do in order to practice and really learn this language. What I'm trying to do is create a clock that will change colors as the time changes, I have the scene drawn but the time doesn't change with it, how do I get the scene to redraw every second?
from time import strftime
from scene import *
current_time = strftime("%b %d %Y %H:%M:%S")
hour = int(strftime("%H"))
min = int(strftime("%M"))
sec = int(strftime("%S"))
class Clock (Scene):
def draw (self):
self.hour = hour
self.min = min
self.sec = sec
background(0, 0, 0)
fill(0, 0, 0)
w, h = self.size.w, self.size.h
rect(w * 0.5 - 100, h * 0.5 - 100, 200, 200)
s = 40 if self.size.w > 700 else 17
text(current_time,
'Futura', s, *self.bounds.center().as_tuple())
dead = set()
run(Clock())
print current_time
print hex(hour)
print hex(min)
print hex(sec)`
You are only calculating the hour, minute, and second once, at the beginning of the script. second doesn't know that it represents the second, it just knows that it's a dumb integer. That's why it doesn't update itself when the time changes.
Try moving the strftimes into the draw method, so they execute every time the screen is redrawn.
def draw (self):
current_time = strftime("%b %d %Y %H:%M:%S")
hour = int(strftime("%H"))
min = int(strftime("%M"))
sec = int(strftime("%S"))
self.hour = hour
self.min = min
self.sec = sec
#...etc

Tkinter clock crashing with infinite loop?

I'm creating a single StringVar called time_display, which contains a string of the fashion 3:14:02, and a single label in the window which should (in theory) reflect updates to said StringVar. However, when I call updateTime to check the time and update it, I crash in an infinite loop. Other adjustments I have made have resulted in no infinite loop but no updating clock either. What am I doing wrong?
from tkinter import *
from tkinter import ttk
import time
root = Tk()
root.title("Clock")
def updateTime(var):
hours = time.localtime().tm_hour
if hours == 0:
hours = 12
minutes = time.localtime().tm_min
if minutes < 10:
minutes = '0' + str(minutes)
else:
minutes = str(minutes)
seconds = time.localtime().tm_sec
if seconds < 10:
seconds = '0' + str(seconds)
else:
seconds = str(seconds)
current_time = str(hours) + ':' + minutes + ':' + seconds
var.set(current_time)
root.after(500, updateTime(var))
time_display = StringVar()
updateTime(time_display)
ttk.Label(root, textvariable=time_display).grid(column=0, row=0)
root.mainloop()
In following line, the code is calling updateTime directly; causing recursive call.
root.after(500, updateTime(var))
# ^ ^
Pass the function and argument without calling it will solve your problem.
root.after(500, updateTime, var)
Alternatively you can use lambda:
root.after(500, lambda: updateTime(var))
BTW, using time.strftime, updateTime can be reduced:
def updateTime(var):
var.set(time.strftime('%H:%M:%S'))
root.after(500, updateTime, var)

Categories