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:
Related
I tired creating a countdown timer. During the duration of the timer the user should be able to enter text. However, it only displays the text after the .after() period (I think thats whats happening at least). It updates after each period and then it displays the text. Is there any workaround for this? Is there any other way to create a countdown timer that would avoid this issue?
import tkinter
from tkinter import *
def showClue(clue):
# Create window
root = tkinter.Tk()
root.state('zoomed')
Grid.rowconfigure(root, 0, weight=1)
Grid.columnconfigure(root, 0, weight=1)
# Frame
clue_frame = tkinter.Frame(root, bg='#0000AF')
clue_frame.pack(expand=True, fill='both')
# Clue label
clue = tkinter.Label(clue_frame, text=clue, bg='#0000AF', fg='white')
clue.config(font=('ITC Korinna Std', 60), wraplength=1250)
# Input
userinput = tkinter.Entry(clue_frame, width=50)
userinput.config(font=('ITC Korinna Std', 25))
# Countdown timer
timer = tkinter.IntVar()
timer.set(15)
time = tkinter.Label(clue_frame,textvariable=timer, bg='#0000AF', fg='white')
time.config(font=('ITC Korinna Std', 50),padx=10,pady=10)
time.pack(anchor='c',expand=True)
clue.pack(anchor= 'c',expand=True)
userinput.pack(anchor='c',expand=True)
timeleft = timer.get()
# Update countdown timer after each second
while timeleft > -1:
root.after(1000)
timer.set(timeleft)
timeleft -= 1
root.update()
root.mainloop()
showClue('test')
What I want this code to do is display the text as the user is typing it and not just after every update.
The root.after method is used to perform some kind of callback as the second parameter for the action it should perform once the time has passed. To fix just create a callback function that updates the variable every second. and continues the countdown inside of the callback.
For example:
import tkinter
from tkinter import *
def countdown(root, timer): # this is the callback function
timeleft = timer.get()
if timeleft > 0:
timer.set(timeleft-1)
root.after(1000, countdown, root, timer) # reschedule callback
def showClue(clue):
# Create window
root = tkinter.Tk()
root.state('zoomed')
Grid.rowconfigure(root, 0, weight=1)
Grid.columnconfigure(root, 0, weight=1)
# Frame
clue_frame = tkinter.Frame(root, bg='#0000AF')
clue_frame.pack(expand=True, fill='both')
# Clue label
clue = tkinter.Label(clue_frame, text=clue, bg='#0000AF', fg='white')
clue.config(font=('ITC Korinna Std', 60), wraplength=1250)
# Input
userinput = tkinter.Entry(clue_frame, width=50)
userinput.config(font=('ITC Korinna Std', 25))
# Countdown timer
timer = tkinter.IntVar()
timer.set(15)
time = tkinter.Label(clue_frame,textvariable=timer, bg='#0000AF', fg='white')
time.config(font=('ITC Korinna Std', 50),padx=10,pady=10)
time.pack(anchor='c',expand=True)
clue.pack(anchor= 'c',expand=True)
userinput.pack(anchor='c',expand=True)
root.after(1000,countdown, root, timer) # start countdown
root.mainloop()
showClue('test')
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.
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()
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.
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( )