Is it possible to embed custom text in python tkcalendar's date Is it possible to embed custom text in python tkcalendar's date tkinter tkinter

Is it possible to embed custom text in python tkcalendar's date


It is not possible from tkcalendar's methods to display text below the day number in the Calendar. However, you don't have to start from scratch, you can create an Agenda class inheriting from Calendar and only rewrite the methods displaying the events to put them inside the day's label instead of in a popup.

To be precise, 3 methods need to be modified: _display_days_without_othermonthdays(), _display_days_with_othermonthdays() and _show_event(), see code below. The code might seem long but I actually only modified a couple of lines in each methods compared to there original version in tkcalendar.

from tkcalendar import Calendarclass Agenda(Calendar):    def __init__(self, master=None, **kw):        Calendar.__init__(self, master, **kw)        # change a bit the options of the labels to improve display        for i, row in enumerate(self._calendar):            for j, label in enumerate(row):                self._cal_frame.rowconfigure(i + 1, uniform=1)                self._cal_frame.columnconfigure(j + 1, uniform=1)                label.configure(justify="center", anchor="n", padding=(1, 4))    def _display_days_without_othermonthdays(self):        year, month = self._date.year, self._date.month        cal = self._cal.monthdays2calendar(year, month)        while len(cal) < 6:            cal.append([(0, i) for i in range(7)])        week_days = {i: 'normal.%s.TLabel' % self._style_prefixe for i in range(7)}  # style names depending on the type of day        week_days[self['weekenddays'][0] - 1] = 'we.%s.TLabel' % self._style_prefixe        week_days[self['weekenddays'][1] - 1] = 'we.%s.TLabel' % self._style_prefixe        _, week_nb, d = self._date.isocalendar()        if d == 7 and self['firstweekday'] == 'sunday':            week_nb += 1        modulo = max(week_nb, 52)        for i_week in range(6):            if i_week == 0 or cal[i_week][0][0]:                self._week_nbs[i_week].configure(text=str((week_nb + i_week - 1) % modulo + 1))            else:                self._week_nbs[i_week].configure(text='')            for i_day in range(7):                day_number, week_day = cal[i_week][i_day]                style = week_days[i_day]                label = self._calendar[i_week][i_day]                label.state(['!disabled'])                if day_number:                    txt = str(day_number)                    label.configure(text=txt, style=style)                    date = self.date(year, month, day_number)                    if date in self._calevent_dates:                        ev_ids = self._calevent_dates[date]                        i = len(ev_ids) - 1                        while i >= 0 and not self.calevents[ev_ids[i]]['tags']:                            i -= 1                        if i >= 0:                            tag = self.calevents[ev_ids[i]]['tags'][-1]                            label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))                        # modified lines:                        text = '%s\n' % day_number + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])                        label.configure(text=text)                else:                    label.configure(text='', style=style)    def _display_days_with_othermonthdays(self):        year, month = self._date.year, self._date.month        cal = self._cal.monthdatescalendar(year, month)        next_m = month + 1        y = year        if next_m == 13:            next_m = 1            y += 1        if len(cal) < 6:            if cal[-1][-1].month == month:                i = 0            else:                i = 1            cal.append(self._cal.monthdatescalendar(y, next_m)[i])            if len(cal) < 6:                cal.append(self._cal.monthdatescalendar(y, next_m)[i + 1])        week_days = {i: 'normal' for i in range(7)}  # style names depending on the type of day        week_days[self['weekenddays'][0] - 1] = 'we'        week_days[self['weekenddays'][1] - 1] = 'we'        prev_m = (month - 2) % 12 + 1        months = {month: '.%s.TLabel' % self._style_prefixe,                  next_m: '_om.%s.TLabel' % self._style_prefixe,                  prev_m: '_om.%s.TLabel' % self._style_prefixe}        week_nb = cal[0][1].isocalendar()[1]        modulo = max(week_nb, 52)        for i_week in range(6):            self._week_nbs[i_week].configure(text=str((week_nb + i_week - 1) % modulo + 1))            for i_day in range(7):                style = week_days[i_day] + months[cal[i_week][i_day].month]                label = self._calendar[i_week][i_day]                label.state(['!disabled'])                txt = str(cal[i_week][i_day].day)                label.configure(text=txt, style=style)                if cal[i_week][i_day] in self._calevent_dates:                    date = cal[i_week][i_day]                    ev_ids = self._calevent_dates[date]                    i = len(ev_ids) - 1                    while i >= 0 and not self.calevents[ev_ids[i]]['tags']:                        i -= 1                    if i >= 0:                        tag = self.calevents[ev_ids[i]]['tags'][-1]                        label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))                    # modified lines:                    text = '%s\n' % date.day + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])                    label.configure(text=text)    def _show_event(self, date):        """Display events on date if visible."""        w, d = self._get_day_coords(date)        if w is not None:            label = self._calendar[w][d]            if not label.cget('text'):                # this is an other month's day and showothermonth is False                return            ev_ids = self._calevent_dates[date]            i = len(ev_ids) - 1            while i >= 0 and not self.calevents[ev_ids[i]]['tags']:                i -= 1            if i >= 0:                tag = self.calevents[ev_ids[i]]['tags'][-1]                label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))            # modified lines:            text = '%s\n' % date.day + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])            label.configure(text=text)if __name__ == '__main__':    import tkinter as tk    root = tk.Tk()    root.geometry("800x500")    agenda = Agenda(root, selectmode='none')    date = agenda.datetime.today() + agenda.timedelta(days=2)    agenda.calevent_create(date, 'Hello World', 'message')    agenda.calevent_create(date, 'Reminder 2', 'reminder')    agenda.calevent_create(date + agenda.timedelta(days=-7), 'Reminder 1', 'reminder')    agenda.calevent_create(date + agenda.timedelta(days=3), 'Message', 'message')    agenda.calevent_create(date + agenda.timedelta(days=3), 'Another message', 'message')    agenda.tag_config('reminder', background='red', foreground='yellow')    agenda.pack(fill="both", expand=True)    root.mainloop()    

screenshot