Tkinter: How to use Radiobutton and grid() to create clickable calendar.
This simple example shows how to use Radiobutton
and grid
(and datetime
) to create calendar for one month.
It also shows how to use command=
in Radiobutton
to execute function which changes text in few Labels
Because command=
expects callback
- it means function's name without ()
and arguments - so I use lambda
to assing function with argument (datetime object with current date) which I can use in function
command=lambda x=current_day:on_click(x)
Full example
import tkinter as tk
import datetime
# --- functions ---
def on_click(date):
#print(date)
label_date['text'] = date.strftime('%a, %b %d, %Y')
label_day['text'] = date.strftime('Day: %d')
label_weekday['text'] = date.strftime('Weekday: %a')
label_yearday['text'] = date.strftime('Day of the year: %-j')
# --- main ---
root = tk.Tk()
radiobutton_var = tk.StringVar()
year = 2020
month = 4
row = 0
for day in range(1, 32):
try:
current_day = datetime.datetime(year, month, day)
date_str = current_day.strftime('%a, %m %d, %Y')
weekday = current_day.weekday()
radiobutton_day = tk.Radiobutton(root,
text=str(day),
indicatoron=0,
variable=radiobutton_var,
value=date_str,
#value=day,
command=lambda x=current_day:on_click(x))
radiobutton_day.grid(row=row, column=weekday, sticky='we')
if weekday == 6:
row += 1
radiobutton_day['bg'] = '#faa'
except ValueError as ex:
print(ex)
break
label_date = tk.Label(root, text='?')
label_date.grid(row=10, columnspan=10)
label_day = tk.Label(root, text='Day: ?')
label_day.grid(row=11, columnspan=10)
label_weekday = tk.Label(root, text='Weekday: ?')
label_weekday.grid(row=12, columnspan=10)
label_yearday = tk.Label(root, text='Day of the year: ?')
label_yearday.grid(row=13, columnspan=10)
root.mainloop()
And code in class inherited from Frame
so it can be used as widget to put many times
import tkinter as tk
import datetime
# --- classes ---
class Month(tk.Frame):
def __init__(self, master, year, month, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.year = year
self.month = month
self.var = tk.StringVar()
self.create()
def on_click(self, date):
#print(date)
self.label_date['text'] = date.strftime('%a, %b %d, %Y')
self.label_day['text'] = date.strftime('Day: %d')
self.label_weekday['text'] = date.strftime('Weekday: %a')
self.label_yearday['text'] = date.strftime('Day of the year: %-j')
def create(self):
year = self.year
month = self.month
row = 0
for day in range(1, 32):
try:
current_day = datetime.datetime(year, month, day)
date_str = current_day.strftime('%a, %m %d, %Y')
weekday = current_day.weekday()
radiobutton_day = tk.Radiobutton(self,
text=str(day),
indicatoron=0,
variable=self.var,
value=date_str,
#value=day,
command=lambda x=current_day:self.on_click(x))
radiobutton_day.grid(row=row, column=weekday, sticky='we')
if weekday == 6:
row += 1
radiobutton_day['bg'] = '#faa'
except ValueError as ex:
print(ex)
break
# add empty label to create empty row when it use less rows
row += 1
while row < 6:
l = tk.Label(self, text=" ")
l.grid(row=row, column=0, sticky='we')
row += 1
self.label_date = tk.Label(self, text='?')
self.label_date.grid(row=10, columnspan=10)
self.label_day = tk.Label(self, text='Day: ?')
self.label_day.grid(row=11, columnspan=10)
self.label_weekday = tk.Label(self, text='Weekday: ?')
self.label_weekday.grid(row=12, columnspan=10)
self.label_yearday = tk.Label(self, text='Day of the year: ?')
self.label_yearday.grid(row=13, columnspan=10)
# --- main ---
root = tk.Tk()
for x in range(1, 3):
m = Month(root, 2020, x)
m.pack(side='left')
root.mainloop()