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.
Related
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.
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:
I need a Python script that uses the Tkinter module to create a static (not resizable) window.
I have a pretty simple Tkinter script but I don't want it to be resizable. How do I prevent a Tkinter window from being resizable? I honestly don't know what to do.
This is my script:
from tkinter import *
import ctypes, os
def callback():
active.set(False)
quitButton.destroy()
JustGo = Button(root, text=" Keep Going!", command= lambda: KeepGoing())
JustGo.pack()
JustGo.place(x=150, y=110)
#root.destroy() # Uncomment this to close the window
def sleep():
if not active.get(): return
root.after(1000, sleep)
timeLeft.set(timeLeft.get()-1)
timeOutLabel['text'] = "Time Left: " + str(timeLeft.get()) #Update the label
if timeLeft.get() == 0: #sleep if timeLeft = 0
os.system("Powercfg -H OFF")
os.system("rundll32.exe powrprof.dll,SetSuspendState 0,1,0")
def KeepGoing():
active.set(True)
sleep()
quitButton1 = Button(root, text="do not sleep!", command=callback)
quitButton1.pack()
quitButton1.place(x=150, y=110)
root = Tk()
root.geometry("400x268")
root.title("Alert")
root.configure(background='light blue')
timeLeft = IntVar()
timeLeft.set(10) # Time in seconds until shutdown
active = BooleanVar()
active.set(True) # Something to show us that countdown is still going.
label = Label(root, text="ALERT this device will go to sleep soon!", fg="red")
label.config(font=("Courier", 12))
label.configure(background='light blue')
label.pack()
timeOutLabel = Label(root, text = 'Time left: ' + str(timeLeft.get()), background='light blue') # Label to show how much time we have left.
timeOutLabel.pack()
quitButton = Button(root, text="do not sleep!", command=callback)
quitButton.pack()
quitButton.place(x=150, y=110)
root.after(0, sleep)
root.mainloop()
The resizable method on the root window takes two boolean parameters to describe whether the window is resizable in the X and Y direction. To make it completely fixed in size, set both parameters to False:
root.resizable(False, False)
from Tkinter import *
import time
#Tkinter stuff
class App(object):
def __init__(self):
self.root = Tk()
self.labeltitle = Label(root, text="", fg="black", font="Helvetica 40 underline bold")
self.labeltitle.pack()
self.labelstep = Label(root, text="", fg="black", font="Helvetica 30 bold")
self.labelstep.pack()
self.labeldesc = Label(root, text="", fg="black", font="Helvetica 30 bold")
self.labeldesc.pack()
self.labeltime = Label(root, text="", fg="black", font="Helvetica 70")
self.labeltime.pack()
self.labelweight = Label(root, text="", fg="black", font="Helvetica 25")
self.labelweight.pack()
self.labelspeed = Label(root, text="", fg="black", font="Helvetica 20")
self.labelspeed.pack()
self.labeltemp = Label(root, text="", fg="black", font="Helvetica 20")
self.labeltemp.pack()
self.button = Button(root, text='Close recipe', width=25, command=root.destroy)
self.button.pack()
def Update(self, label, change):
label.config(text=str(change))
def main():
app = App()
app.mainloop()
if __name__ == "__main__":
main()
I'm trying to create a recipe display which will show the step, instructions, weight and other variables on a screen in a Tkinter GUI.
However, I do not know how to update the GUI to change with each new step of the recipe, as the content has to be dynamically updated based on user input (taken from a server). How can I achieve updating of the GUI's other elements based on the change in steps?
You can use after() to run function after (for example) 1000 miliseconds (1 second) to do something and update text on labels. This function can run itself after 1000 miliseconds again (and again).
It is example with current time
from Tkinter import *
import datetime
root = Tk()
lab = Label(root)
lab.pack()
def clock():
time = datetime.datetime.now().strftime("Time: %H:%M:%S")
lab.config(text=time)
#lab['text'] = time
root.after(1000, clock) # run itself again after 1000 ms
# run first time
clock()
root.mainloop()
BTW: you could use StringVar as sundar nataraj Сундар suggested
EDIT: (2022.01.01)
Updated to Python 3 with other changes suggested by PEP 8 -- Style Guide for Python Code
import tkinter as tk # PEP8: `import *` is not preferred
import datetime
# --- functions ---
# PEP8: all functions before main code
# PEP8: `lower_case_name` for funcitons
# PEP8: verb as function's name
def update_clock():
# get current time as text
current_time = datetime.datetime.now().strftime("Time: %H:%M:%S")
# udpate text in Label
lab.config(text=current_time)
#lab['text'] = current_time
# run itself again after 1000 ms
root.after(1000, update_clock)
# --- main ---
root = tk.Tk()
lab = tk.Label(root)
lab.pack()
# run first time at once
update_clock()
# run furst time after 1000ms (1s)
#root.after(1000, update_clock)
root.mainloop()
if you want to change label dynamically
self.dynamiclabel=StringVar()
self.labeltitle = Label(root, text=self.dynamiclabel, fg="black", font="Helvetica 40 underline bold")
self.dyanamiclabel.set("this label updates upon change")
self.labeltitle.pack()
when ever you get new value then just use .set()
self.dyanamiclabel.set("Hurrray! i got changed")
this apply to all the labels.To know more read this docs
If you are using labels, then you can use this:
label = tk.Label(self.frame, bg="green", text="something")
label.place(rely=0, relx=0.05, relwidth=0.9, relheight=0.15)
refresh = tk.Button(frame, bg="white", text="Refreshbutton",command=change_text)
refresh.pack(rely=0, relx=0.05, relwidth=0.9, relheight=0.15)
def change_text()
label["text"] = "something else"
Works fine for me, but it is dependent on the need of a button press.
I added a process bar in my window, and change its value according to randint for every 1 second using the update function:
from random import randint
def update():
mpb["value"] = randint(0, 100) # take process bar for example
window.after(1000, update)
update()
window.mainloop()
I wrote an example with Python 3.7
from tkinter import *
def firstFrame(window):
global first_frame
first_frame = Frame(window)
first_frame.place(in_=window, anchor="c", relx=.5, rely=.5)
Label(first_frame, text="ATTENTION !").grid(row=1,column=1,columnspan=3)
def secondFrame(window):
global second_frame
second_frame= Frame(window, highlightbackground=color_green, highlightcolor=color_green, highlightthickness=3)
second_frame.place(in_=window, anchor="c", relx=.5, rely=.5)
Label(second_frame, text="This is second frame.").grid(row=1, column=1, columnspan=3, padx=25, pady=(15, 0))
window = Tk()
window.title('Some Title')
window.attributes("-fullscreen", False)
window.resizable(width=True, height=True)
window.geometry('300x200')
firstFrame(window)
secondFrame(window)
first_frame.tkraise()
window.after(5000, lambda: first_frame.destroy()) # you can try different things here
window.mainloop()
Use root.config() and add a way to run
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( )