How to make a live date display using Python and tkinter - python-3.x

I'm trying to make an info center and I need to add a live date display, so every day it adds another day to it, if a month passes it would add a month to it. How would I do it?
I've googled and still have no idea, I know how to display it but no clue how to make it automatically update. would it be possible to do it like this below?
def tick():
time_string = time.strftime("%H:%M:%S")
clock.config(text=time_string)
clock.after(200, tick)
root = Tk()
clock = Label(root, font=("none", 50, "bold"), bg="#000000", fg="#910000", bd=5, relief="ridge")
clock.grid(row=0, column=0)
tick()
root.mainloop()

Your logic is fine. If you want to display months and days, you can use datetime module instead:
from datetime import datetime
def tick():
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
clock.config(text=now)
clock.after(200, tick)

Related

schedule, calendar, tinter and Threading

I want to create a schedule that can update the calendar daily.
I'm using the code below but it seems I'm using the Thread or the Schedule in the wrong way.
If I use Calendar only, the date will never change.
from tkinter import *
import threading
import schedule
import calendar
from tkcalendar import *
root = Tk()
box = Frame(root, width=500, height=550,highlightbackground="red", highlightthickness=5)
box.grid(row=0, column=1)
root.geometry('1000x500')
crm = Calendar (root, firstweekday='sunday',selectmode='none',showweeknumbers=False,
font=('Helvetica',15, 'bold'),
fill='both',expand=True)
calendar.setfirstweekday(calendar.SUNDAY)
crm.grid(ipady=110,ipadx=250,row=0,column=0)
def job1():
threading.Thread(target=job2).start()
def job2():
print('its time')# HERE I WANT to the Schedule UPDATE the Calendar
schedule.every().day.at("00:00").do(job1)
schedule.run_all()
root.mainloop()
I found a way to use the schedule inside a loop so I can manage to update the calendar after midnight.
i used (schedule.run_pending() ) inside the loop. no need for threading.

How to adjust Label in tkinter?

I am making a program that uses this equation:
16*(falling_speed)^2 = height
This basically takes the time you are falling and uses it to determine how high you are falling from.
I know how to use the equation, but my question is this, how to adjust the label to 1 second or 2 seconds?
I tried to make them seperate labels, but that didn't work either.
Here is my code:
from tkinter import *
from time import *
print("""This is an app that basically you time the amount of time someone takes to fall from a cliff, then we will
use an equation to tell you how high the cliff is.
This is a recreation of the app Mark Rober created, by The way""")
window = Tk()
window.title("falling app")
window.geometry("700x700")
window.configure(bg = "sky blue")
"""We will use time import for this"""
timer = Label(window, text = "0:00", font = ("verdana", 60))
timer.place(relx = 0.4, rely = 0.35, anchor = "nw")
def start():
mins = 0
seconds = 0
while seconds != 60:
sleep(1.00)
seconds+=1
if seconds == 60:
mins = mins+1
seconds = 0
This line: timer = Label(window, text = "0:00", font = ("verdana", 60))
is what makes the text. Is there a way to change text after you have created it?
Thanks in advance!!!
You can use timer["text"] = "some_text", or timer.config(text="some_text").
All widgets have the configure method which you can find good reference here.

Retrive date from DateTimeCtrl WXPython

Hey all im having a difficult time with something I believe should be rather simple. Im using WXpython(3.X) to make my GUI and i'm using DatePickerCtrl to form my control. All im trying to do is retrieve the value when I change it. I used the GetValue() method but that only returns the date that currently shows not the one that I changed it to. Then I tried using DateEvent.GetDate but I keep getting an error.
def getStartDate(self):
a = wx.adv.DateEvent(self, self.date_Begin.GetValue(), Event.SetTimestamp()).GetDate
print(a)
return a
and the error that shows up is
**Event.SetTimestamp(): first argument of unbound method must have type 'Event'**
You have declared def getStartDate(self): rather than def getStartDate(self,event):, so you aren't allowing for the event sent to the function.
There is only one event emitted by this function EVT_DATE_CHANGED.
import wx
import datetime
import wx.adv
#----------------------------------------------------------------------
class TestPanel(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
dpc1 = wx.adv.DatePickerCtrl( self, wx.ID_ANY, wx.DefaultDateTime)
self.Bind(wx.adv.EVT_DATE_CHANGED, self.OnDateChanged, dpc1)
sizer.Add(dpc1, 0, wx.ALL, 50)
# In some cases the widget used above will be a native date
# picker, so show the generic one too.
dpc2 = wx.adv.GenericDatePickerCtrl(self, size=(120,-1),
style = wx.TAB_TRAVERSAL
| wx.adv.DP_DROPDOWN
| wx.adv.DP_SHOWCENTURY
| wx.adv.DP_ALLOWNONE )
self.Bind(wx.adv.EVT_DATE_CHANGED, self.OnDateChanged, dpc2)
sizer.Add(dpc2, 0, wx.LEFT, 50)
now = wx.DateTime.Now()
print (wx.DateTime.FormatISODate(now))
print (wx.DateTime.Format(now))
dpc2.SetValue(wx.DateTime.Now())
def OnDateChanged(self, evt):
sel_date = evt.GetDate()
print (sel_date.Format("%d-%m-%Y"))
#----------------------------------------------------------------------
if __name__ == '__main__':
app = wx.App()
frame = TestPanel()
frame.Show()
app.MainLoop()
Above I reformat the date to dd/mm/yyyy, as I am not from the USA.
If you want more control use wx.adv.CalendarCtrl
You should be able to bind your DatePickerCtrl widget to wx.adv.EVT_DATE_CHANGED
Then in your event handler, you would do something like this:
def OnDateChanged(self, evt):
new_date = evt.GetDate()
print(new_date)
return new_date
Check out the wxPython demo as it has a good example of this widget as well as most of the others.

Formatting entered text in Python Tkinter Entry widget after user interacts with another widget

If a user enters 25000 into a tkinter entry widget, is there a way to make the widget automatically display the text that was just entered as $25,000.00 once the user interacts with anything else? I've used '${:.,2f}'.format() in other projects, but I'm not sure how to use it with tkinter. Perhaps there is another method entirely when building code in tkinter. Thanks in advance for any advice you might have to offer!
from tkinter import *
from tkinter import messagebox
window=Tk()
window.title("APY Accrued Value Calculator")
def Button1Function():
exit()
def Button2Function(Entry1,Entry2,Entry3):
while True:
if Entry1==0 or Entry2==0 or Entry3==0:
messagebox.showerror("Error Detected","All fields must have a
number value greater than zero")
return None
if Entry3==int(Entry3):
Entry3=int(Entry3)
else:
messagebox.showerror("Error Detected","Number of years must be
a whole number.")
return None
try:
if Entry2==int(Entry2):
Entry2=int(Entry2)
except: pass
AccruingAmount=Entry1
for i in range(0,Entry3):
AccruingAmount=AccruingAmount*(1+(Entry2/100))
Entry1='${:,.2f}'.format(Entry1)
Entry2='{}%'.format(Entry2)
AccruingAmount='${:,.2f}'.format(AccruingAmount)
message="
"
CalculationMessage=Message(window,width=345,text=message)
message="If "+Entry1+" is deposited and left for "+str(Entry3)+"
years at an annual interest rate of "+Entry2+", your final return will be:
"+AccruingAmount+"."
CalculationMessage=Message(window,width=345,text=message)
CalculationMessage.grid(row=12,column=0,sticky=(N),pady=(5,0))
break
Label1=Label(window,text="Starting amount:")
Label1.grid(column=0,sticky=(W),padx=(5,0))
StrVar1=StringVar()
Entry1=Entry(window,textvariable=StrVar1)
Entry1.grid(column=0,sticky=(W),padx=(5,0))
Label2=Label(window,text="APY percentage rate:")
Label2.grid(row=3,column=0,sticky=(W),padx=(5,0),pady=(10,0))
StrVar2=StringVar()
Entry2=Entry(window, textvariable=StrVar2)
Entry2.grid(column=0,sticky=(W),padx=(5,0))
Label3=Label(window,text="Number of years that starting amount will be
accruing interest:")
Label3.grid(row=6,column=0,columnspan=2,sticky=(W),padx=(5,0),pady=(10,0))
StrVar3=StringVar()
Entry3=Entry(window, textvariable=StrVar3)
Entry3.grid(row=7,column=0,sticky=(W),padx=(5,0))
BlankRow3=Label(window,text="Calculation results:",font=("bold"))
BlankRow3.grid(row=8,column=0,pady=(10,0))
CalculationBox=Canvas(window,borderwidth=2,width=350,height=25)
CalculationBox.grid(row=12,column=0)
Button1=Button(window,text="Close",width=12,command=Button1Function)
Button1.grid(row=13,column=0,sticky=(W),padx=(5,0),pady=(0,5))
try:
Button2=Button(window,text="Calculate",width=12,command=lambda: Button2Function(float(Entry1.get()),float(Entry2.get()),float(Entry3.get())))
Button2.grid(row=13,column=0,sticky=(E),padx=(0,5),pady=(0,5))
except: messagebox.showerror("Error Detected","Numbers must be entered
into all fields.")
window.mainloop()
Try this code:
import tkinter as tk
root = tk.Tk()
amount = tk.Label(root,text = "$0.00")
amount.grid(row=1,column=0)
def updat():
try:amount.config(text="${:,.2f}".format(float(entry.get())))
except:amount.config(text = "$0.00")
entry = tk.Entry(root)
entry.grid(row=0,column=0)
entry.bind("<Key>",lambda v: root.after(10,updat))
root.mainloop()
Running:

How to create GUI objects one by one with Tkinter

I like to create an object per second and make the show up one by one. However, the code below wait for 3 seconds and show them all at the same time.
from tkinter import *
import time
def create():
for i in range(3):
r4=Radiobutton(root, text="Option 1"+str(i), value=1)
r4.pack( anchor = W )
time.sleep(1)
root = Tk()
create()
root.mainloop()
Your code, as is, creates a one object per second as you desired it, but this objects need to be shown, and they're shown when code flow reaches the mainloop. Hence, for observer, it looks like there're no objects at all after one second.
Of course, you can use sleep and update, but beware - sleeping leads to unresponsive window, so it's OK option (to be honest - not OK at all), if your application isn't drawn and you're outside of mainloop, but if it's not - prepare for a "frozen" window, because GUI can redraw himself only in mainloop (an event loop, you can reach it with update as well) and sleep blocks this behaviour.
But there's a good alternative, the after method, take a look on it!
And there's a snippet, so you can see the difference:
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
import time
def create_with_sleep():
for _ in range(3):
tk.Radiobutton(frame_for_sleep, text="Sleep Option").pack(anchor='w')
time.sleep(int(time_entry.get()))
root.update()
def create_with_after(times=3):
if times != 0:
tk.Radiobutton(frame_for_after, text="After Option").pack(anchor='w')
times -= 1
root.after(int(time_entry.get()) * 1000, lambda: create_with_after(times))
root = tk.Tk()
test_yard_frame = tk.Frame(root)
frame_for_sleep = tk.Frame(test_yard_frame)
frame_for_after = tk.Frame(test_yard_frame)
test_yard_frame.pack()
frame_for_sleep.pack(side='left')
frame_for_after.pack(side='left')
button_frame = tk.Frame(root)
button_for_sleep = tk.Button(button_frame, text='Create 3 radiobuttons with sleep+update', command=create_with_sleep)
button_for_after = tk.Button(button_frame, text='Create 3 radiobuttons with after', command=create_with_after)
button_frame.pack()
button_for_sleep.pack(side='left')
button_for_after.pack(side='left')
time_label = tk.Label(root, text='Time delay in seconds:')
time_label.pack(fill='x')
time_entry = tk.Entry(root)
time_entry.insert(0, 1)
time_entry.pack(fill='x')
root.mainloop()
With 1 seconds delay there's no much difference, but you can try to increase delay to understand why after option is preferable in general.
You can use update to call a refresh on your objects.
In use, you would have to add the line root.update() in your for loop.

Resources