select date in tkinter without tkcalendar

1.6k Views Asked by At

I am looking for a way to display a calendar or other date picker inside a tkinter window. I am aware of tkcalendar and it works great. However, I am looking for a way to achieve this without tkcalendar, because tkcalendar is licensed under GPLv3. I scoured the internet and all forums I found say unanimously, that a code including the words "import tkcalendar", even when not compiled, is considered a derived work and must therefore also be licensed under GPLv3. None of those threats had answers from legal experts, but I don't want to take the risk of importing anything licensed under GLP.

Can somebody suggest alternatives to tkcalendar or a suggestion on how to recreate it without copying from the source code?

Edit: I have been asked to add an explanation for what my problem with GPL is. My problem is that, as far as I understand it, a code importing tkcalendar is considered a "derived work" of tkcalendar and is therefore required to also be licensed under GPL. I don't want to license my program under GPL though, so as far as I understand it, I cannot import any GPL-licensed modules.

1

There are 1 best solutions below

0
On

You can create a calendar pretty easily by using the output of calendar.monthcalendar. Just iterate over the data, creating buttons for each day.

Here's a rudimentary example. It's not complete solution, but it does show how to create the widgets and print out the day the user clicked on.

import tkinter as tk
import calendar

class CalendarWidget(tk.Frame):
    def __init__(self, parent, year, month, **kwargs):
        super().__init__(parent, **kwargs)

        self.cal_frame = tk.Frame(self)
        self.cal_frame.pack(side="top", fill="x")

        self.redraw(year, month)

    def redraw(self, year, month):
        '''Redraws the calendar for the given year and month'''

        for child in self.cal_frame.winfo_children():
            child.destroy()

        # day of the week headings
        for col, day in enumerate(("Mo", "Tu", "We", "Th", "Fr", "Sa", "Su")):
            label = tk.Label(self.cal_frame, text=day)
            label.grid(row=0, column=col, sticky="nsew")

        # buttons for each day
        cal = calendar.monthcalendar(year, month)
        for row, week in enumerate(cal):
            for col, day in enumerate(week):
                text = "" if day == 0 else day
                state = "normal" if day > 0 else "disabled"
                cell = tk.Button(self.cal_frame, text=text, state=state, command=lambda day=day: self.set_day(day))
                cell.grid(row=row+1, column=col, sticky="nsew")

    def set_day(self, num):
        print(f"you selected day {num}")

root = tk.Tk()
c = CalendarWidget(root, year=2022, month=4, bd=2, relief="groove")
c.pack(padx=4, pady=4)

root.mainloop()

screenshot of custom widget