Bartłomiej 'furas' Burek
furas.pl
# prywatne notatki - Python, Linux, Machine Learning, etc.

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()
python tkinter radiobutton calendar

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()
python tkinter radiobutton calendar
Książki: python-dla-kazdego-podstawy-programowania python-wprowadzenie python-leksykon-kieszonkowy python-receptury python-programuj-szybko-i-wydajnie python-projekty-do-wykorzystania black-hat-python-jezyk-python-dla-hackerow-i-pentesterow efektywny-python-59-sposobow-na-lepszy-kod tdd-w-praktyce-niezawodny-kod-w-jezyku-python aplikacje-internetowe-z-django-najlepsze-receptury