Digital clock in status bar in python 3 and tkinter - python

I want to put this digital clock:
import sys
from tkinter import *
import time
root = Tk()
time1 = ''
clock = Label(root, font=('times', 20, 'bold'), bg='green')
clock.pack(fill=BOTH, expand=1)
def tick():
global time1
# get the current local time from the PC
time2 = time.strftime('%H:%M:%S')
# if time string has changed, update it
if time2 != time1:
time1 = time2
clock.config(text=time2)
# calls itself every 200 milliseconds
# to update the time display as needed
# could use >200 ms, but display gets jerky
clock.after(200, tick)
tick()
root.mainloop( )
in this status bar:
status = Label(mGui, text="v1.0", bd=1, relief=SUNKEN, anchor=W)
status.pack(side=BOTTOM, fill=X)
Is there a way to do that?
Thanks everyone who want to help, I appreciate it :)

What is with the if statement? It is unnecessary as the clock.after statement is calling tick() directly within the clock.after() function, to which updates your time string.
import sys
from Tkinter import *
import time
def tick():
# get the current local time from the PC
time_string = time.strftime('%H:%M:%S')
# if time string has changed, update it
clock.config(text=time_string)
clock.after(200, tick)
root = Tk()
clock = Label(root, font=('times', 20, 'bold'), bg='green')
clock.grid(row=0, column=1)
tick()
root.mainloop()
Also, remember to use Tkinter (Capital T) for Python 2.7 and tkinter (lowercase t) for Python 3.0.

Tkinter noob here, but i don't think you can put the clock label inside the status label. However you can put them side by side:
import sys
from tkinter import *
import time
def tick():
global time1
# get the current local time from the PC
time2 = time.strftime('%H:%M:%S')
# if time string has changed, update it
if time2 != time1:
time1 = time2
clock.config(text=time2)
# calls itself every 200 milliseconds
# to update the time display as needed
# could use >200 ms, but display gets jerky
clock.after(200, tick)
root = Tk()
time1 = ''
status = Label(root, text="v1.0", bd=1, relief=SUNKEN, anchor=W)
status.grid(row=0, column=0)
clock = Label(root, font=('times', 20, 'bold'), bg='green')
clock.grid(row=0, column=1)
tick()
root.mainloop()

Normally, I make a statusbar out of a frame, and then pack whatever things I want to display in that frame. For example, your clock could be packed on the right side, and your status label could be packed on the left. Then you can put the whole statusbar frame at the bottom of your GUI.
Normally I prefer to give examples using an object-oriented style, but here's an example adapted from the code in your question:
import sys
from tkinter import *
import time
root = Tk()
statusbar = Frame(root)
statusbar.pack(side="bottom", fill="x", expand=False)
time1 = ''
clock = Label(root, font=('times', 20, 'bold'), bg='green')
def tick():
global time1
# get the current local time from the PC
time2 = time.strftime('%H:%M:%S')
# if time string has changed, update it
if time2 != time1:
time1 = time2
clock.config(text=time2)
# calls itself every 200 milliseconds
# to update the time display as needed
# could use >200 ms, but display gets jerky
clock.after(200, tick)
tick()
status = Label(root, text="v1.0", bd=1, relief=SUNKEN, anchor=W)
status.pack(in_=statusbar, side=LEFT, fill=BOTH, expand=True)
clock.pack(in_=statusbar, side=RIGHT, fill=Y, expand=False)
root.mainloop( )

Related

Call a fonction from message box Tkinter

I want to call the fonction (submit) after clicking on the message box. With this code I have to reclick on button everytime after the messagebox but would appreciate if the timer launch automatically after clicking on the message box.
If anyone have a clue I will appreciate.
The following code :
import time
from tkinter import *
root = Tk()
root.resizable(width=False, height=False)
root.geometry("300x250")
root['background']='#39E5F9'
root.title("Time To Drink Water")
minute = StringVar()
second = StringVar()
minute.set("45")
second.set("00")
minuteEntry = Entry(root, width=3, font=("Arial", 35, ""),
textvariable=minute,justify='center')
minuteEntry.place(x=50, y=60)
secondEntry = Entry(root, width=3, font=("Arial", 35, ""),
textvariable=second,justify='center')
secondEntry.place(x=170, y=60)
def submit():
# stored in here : 2700 = 45 mins
temp = 2700
while temp > -1:
# divmod(firstvalue = temp//60, secondvalue = temp%60)
mins, secs = divmod(temp, 60)
if mins > 60:
hours, mins = divmod(mins, 60)
minute.set("{0:2d}".format(mins))
second.set("{0:2d}".format(secs))
root.update()
time.sleep(1)
if (temp == 0):
messagebox.showinfo("Time Countdown", "Time To Drink !")
temp -= 1
def go():
btn = Button(root, text='Goodbye dehydration!', bd='6',
command=submit)
btn.place(x=90, y=160)
go()
root.mainloop()
messagebox is waiting for your click so you can run submit() after messagebox and it will run it after clicking in messagebox
But you shouldn't use while and sleep because it may freeze GUI (in any framework, and in any language). You can use root.after(1000, function) to run function again after 1000ms (1s) and it will work as sleep and while together.
import time
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import messagebox
# --- functions --- # PEP8: all functions before main code
def submit():
update_counter(2700)
def update_counter(temp):
if temp > -1: # `if` instead of `while` because `after` will work as loop
# divmod(firstvalue = temp//60, secondvalue = temp%60)
mins, secs = divmod(temp, 60)
if mins > 60:
hours, mins = divmod(mins, 60)
minute.set("{:02d}".format(mins)) # use `:02` to get `09` instead of ` 9` (with space)
second.set("{:02d}".format(secs))
temp -= 1
root.after(1000, update_counter, temp) # run again after 1000ms
else:
messagebox.showinfo("Time Countdown", "Time To Drink !")
root.after(0, update_counter, 2700) # run again after 0ms
#update_counter(2700) # run again
# --- main --- # PEP8: `lower_case_names` for variables
running = False
temp = 2700
root = tk.Tk()
minute = tk.StringVar(root)
second = tk.StringVar(root)
minute.set("45")
second.set("00")
minute_entry = tk.Entry(root, width=3, textvariable=minute, font=("Arial", 35, ""), justify='center')
minute_entry.grid(row=0, column=0)
second_entry = tk.Entry(root, width=3, textvariable=second, font=("Arial", 35, ""), justify='center')
second_entry.grid(row=0, column=1)
btn = tk.Button(root, text='Goodbye dehydration!', command=submit)
btn.grid(row=1, column=0, columnspan=2)
root.mainloop()
PEP 8 -- Style Guide for Python Code
There is other problem. You can click button two times and it will run two update_counter() at the same time. It may need to disable button, or you would have to use boolean variable - ie. running = False - to control if it has to run update_counter() or not.

Add a label/text (ideally positioned above a countdown timer) using tkinter

I added the label tag which I thought would solve the problem but when I run the project nothing happens so I kinda at my wit's end also I doing this project is that is important at all to the problem and the ide is Thonny.
#!/usr/bin/python
from tkinter import *
from tkinter import ttk
from tkinter import font
import time
import datetime
global endTime
def quit(*args):
root.destroy()
def show_time():
# Get the time remaining until the event
remainder = endTime - datetime.datetime.now()
# remove the microseconds part
remainder = remainder - datetime.timedelta(microseconds=remainder.microseconds)
# Show the time left
txt.set(remainder)
# Trigger the countdown after 1000ms
root.after(1000, show_time)
# Use tkinter lib for showing the clock
root = Tk()
label(root,text="timer", bg="black", fg=Fdf800")
root.attributes("-fullscreen", True)
root.configure(background='black')
root.bind("x", quit)
root.after(1000, show_time)
# Set the end date and time for the countdown
endTime = datetime.datetime(2017, 9, 19, 9, 0, 0)
fnt = font.Font(family='Helvetica', size=60, weight='bold')
txt = StringVar()
lbl = ttk.Label(root, textvariable=txt, font=fnt, foreground="green", background="black")
lbl.place(relx=0.5, rely=0.5, anchor=CENTER)
root.mainloop()
You need to place a tk.Label() using .pack(), .grid() or .place().
For your use case, it seems .pack() would be suitable; you will want to use this for all your widgets for consistency, e.g.
label = Label(root,text="timer", bg="black")
label.pack()
Full (modified) code:
from tkinter import *
from tkinter import ttk
from tkinter import font
import time
import datetime
def quit(*args):
root.destroy()
def show_time():
# Get the time remaining until the event
remainder = endTime - datetime.datetime.now()
# remove the microseconds part
remainder = remainder - datetime.timedelta(microseconds=remainder.microseconds)
# Show the time left
txt.set(remainder)
# Trigger the countdown after 1000ms
root.after(1000, show_time)
# Use tkinter lib for showing the clock
root = Tk()
label = Label(root,text="timer", bg="black", fg="red")
label.pack()
root.attributes("-fullscreen", True)
root.configure(background='black')
root.bind("x", quit)
root.after(1000, show_time)
# Set the end date and time for the countdown
endTime = datetime.datetime(2017, 9, 19, 9, 0, 0)
fnt = font.Font(family='Helvetica', size=60, weight='bold')
txt = StringVar()
lbl = ttk.Label(root, textvariable=txt, font=fnt, foreground="green", background="black")
lbl.pack()
root.mainloop()
Which produces the result:

Attempting to make countdown timer with Tkinter

I am attempting to make a clock using python's Tkinter. It works but not in the way I intended. Once the user enters the amount of time that needs to be counted down from, the action is performed but the actual countdown isn't being shown. I would like for the user to have the ability to watch the numbers go all the way until 0. Any help is greatly appreciated.
import time
from tkinter import *
root = Tk()
def countdown(t):
ts = int(t)
while ts > 0:
timer = Label(timerFrame, text = ts)
ts-=1
timer.pack()
time.sleep(1)
if ts ==0:
timer.destroy()
completeTimer = Label(timerFrame, text="Time is complete")
completeTimer.pack()
timerFrame = LabelFrame(root, padx=50, pady=50, bd=0)
timerFrameText = Label(timerFrame,
text="Enter time in seconds for countdown",
font=("Arial", 20, "bold")
)
countdownBox= Entry(timerFrame, bd=3)
submitCountdown = Button(timerFrame,
padx=5,
pady=5,
text="Submit",
font=("Arial", 20),
command= lambda:countdown(countdownBox.get())
)
timerFrame.pack()
timerFrameText.pack()
countdownBox.pack()
submitCountdown.pack()
root.mainloop()
You can try this one I've implemented Threading. This allows you to run threads or let's say processes synchronously. In creating GUI applications and such as timers or any other program that needs to be run all at the same time it's really important that to learn Multithreading and MultiProcessing. It's a really huge factor in software development.
import time
from tkinter import *
import threading
root = Tk()
def cd(timer_label_obj,ts):
while ts > 0:
timer_label_obj.config(text=ts)
ts-=1
timer_label_obj.pack()
time.sleep(1)
if ts ==0:
timer_label_obj.destroy()
completeTimer = Label(timerFrame, text="Time is complete")
completeTimer.pack()
def countdown(t):
timer = Label(timerFrame)
ts = int(t)
th = threading.Thread(target=cd,args=[timer,ts])
th.start()
timerFrame = LabelFrame(root, padx=50, pady=50, bd=0)
timerFrameText = Label(timerFrame,
text="Enter time in seconds for countdown",
font=("Arial", 20, "bold")
)
countdownBox= Entry(timerFrame, bd=3)
submitCountdown = Button(timerFrame,
padx=5,
pady=5,
text="Submit",
font=("Arial", 20),
command= lambda:countdown(countdownBox.get())
)
timerFrame.pack()
timerFrameText.pack()
countdownBox.pack()
submitCountdown.pack()
root.mainloop()
Maybe adding some kind of print statement with your ts value will help. Never used tkinter, but it looks like you only print when it finishes count down. Or try to print ts as a string like in a normal print statment:
print("current count %s" %ts)

Python counting down to a series of times every day

My goal is to create a countdown that will display the minutes and seconds remaining until a specific time of day and then, when that's reached, count down to the next one.
What I have so far will countdown to a specific date and time using datetime.datetime and then stop.
I currently have two problems: How to count down using time, not datetime so that it will be the same every day (i.e. countdown to noon every day, not countdown to noon on a specific date). My second problem is how to move on to the next time to count to (I assume that's a matter of just pulling a new time when seconds_left = 0 but I'm not sure).
Here's where I'm at so far:
#!/usr/bin/python
from tkinter import *
from tkinter import ttk
from tkinter import font
import time
import datetime
global endTime
def quit(*args):
root.destroy()
def show_time():
# Get the time remaining until the event
remainder = endTime - datetime.datetime.now()
# remove the microseconds part
remainder = remainder - datetime.timedelta(microseconds=remainder.microseconds)
# Show the time left
txt.set(remainder)
# Trigger the countdown after 1000ms
root.after(1000, show_time)
# Use tkinter lib for showing the clock
root = Tk()
root.attributes("-fullscreen", True)
root.configure(background='black')
root.bind("x", quit)
root.after(1000, show_time)
# Set the end date and time for the countdown
endTime = datetime.datetime(2017, 9, 19, 9, 0, 0)
fnt = font.Font(family='Helvetica', size=60, weight='bold')
txt = StringVar()
lbl = ttk.Label(root, textvariable=txt, font=fnt, foreground="green", background="black")
lbl.place(relx=0.5, rely=0.5, anchor=CENTER)
root.mainloop()
datetime works just fine. What you need is a conditional statement in your show_time function to update your endTime.
Example using datetime with now() and year, month, day to build the next endTime.
import tkinter as tk
from tkinter import ttk
from tkinter import font
import datetime as dt
def quit(*args):
root.destroy()
def show_time():
global endTime
remainder = endTime - dt.datetime.now()
remainder = remainder - dt.timedelta(microseconds=remainder.microseconds)
if remainder.total_seconds() < 0:
y = dt.datetime.now().year
m = dt.datetime.now().month
d = dt.datetime.now().day
endTime = dt.datetime(y, m, d, 9, 0, 0) + dt.timedelta(days=1)
txt.set(remainder)
root.after(1000, show_time)
root = tk.Tk()
root.attributes("-fullscreen", True)
root.configure(background='black')
root.bind("x", quit)
root.after(1000, show_time)
endTime = dt.datetime(2017, 9, 19, 9, 0, 0)
fnt = font.Font(family='Helvetica', size=60, weight='bold')
txt = tk.StringVar()
lbl = ttk.Label(root, textvariable=txt, font=fnt, foreground="green", background="black")
lbl.place(relx=0.5, rely=0.5, anchor='center')
root.mainloop()

Combine two windows with tkinter

I have just started playing with tkinter today and I have two bit of code I have been playing with as examples however I am struggling to combine these can anyone advise. I would like to clock to display in the main window.
import tkinter
from tkinter import *
import sys
import time
root = Tk()
root.title('Logging')
Label(text='Time logging').pack(side=TOP,padx=100,pady=100)
entry = Entry(root, width=25)
entry.pack(side=TOP,padx=25,pady=25)
def onok():
x, y = entry.get().split('x')
for row in range(int(y)):
for col in range(int(x)):
print((col, row))
Button(root, text='Log Time', command=onok).pack(side=LEFT)
Button(root, text='CLOSE').pack(side= RIGHT)
def tick():
global time1
# get the current local time from the PC
time2 = time.strftime('%H:%M:%S')
# if time string has changed, update it
if time2 != time1:
time1 = time2
clock.config(text=time2)
# calls itself every 200 milliseconds
# to update the time display as needed
# could use >200 ms, but display gets jerky
clock.after(200, tick)
root = Tk()
time1 = ''
status = Label(root, text="v1.0", bd=1, relief=SUNKEN, anchor=W)
status.grid(row=10, column=10)
clock = Label(root, font=('times', 20, 'bold'), bg='green')
clock.grid(row=0, column=1)
tick()
root.mainloop()
You can use Frame to group clock widgets and use grid inside this frame. And frame you can put in main window. (And you don't need second Tk())
I put it at the top but you can choose other place.
import tkinter as tk
import time
# --- functions ---
def on_ok():
x, y = entry.get().split('x')
for row in range(int(y)):
for col in range(int(x)):
print((col, row))
def tick():
global time1
# get the current local time from the PC
time2 = time.strftime('%H:%M:%S')
# if time string has changed, update it
if time2 != time1:
time1 = time2
clock.config(text=time2)
# calls itself every 200 milliseconds
# to update the time display as needed
# could use >200 ms, but display gets jerky
clock.after(200, tick)
# --- main window ---
time1 = ''
root = tk.Tk()
root.title('Logging')
# add frame in main window (root)
other = tk.Frame(root)
other.pack()
# put widgets in frame (other)
status = tk.Label(other, text="v1.0", bd=1, relief=tk.SUNKEN, anchor=tk.W)
status.grid(row=10, column=10)
clock = tk.Label(other, font=('times', 20, 'bold'), bg='green')
clock.grid(row=0, column=1)
# put other widget directly in main widnow (root)
tk.Label(root, text='Time logging').pack(side=tk.TOP, padx=100, pady=100)
entry = tk.Entry(root, width=25)
entry.pack(side=tk.TOP, padx=25, pady=25)
tk.Button(root, text='Log Time', command=on_ok).pack(side=tk.LEFT)
tk.Button(root, text='CLOSE', command=root.destroy).pack(side= tk.RIGHT)
tick()
# --- start ---
root.mainloop()
You have two different root windows. Use one root = Tk() line at the top and you should have them on the same page.

Categories

Resources