j4321 / tkcalendar

Calendar widget for Tkinter
https://pypi.python.org/pypi/tkcalendar
GNU General Public License v3.0
97 stars 33 forks source link

Click on a "calevent" at previous/next month jumps to a wrong date and 2 more issues #88

Open siriuskht opened 2 years ago

siriuskht commented 2 years ago

OS: Windows 10 Python Version: 3.9 IDE: Thonny 3.3.14 TKCalendar Version: 1.6.1

Hello together, I hope that there is still some development/bug fixing of the nice TKCalender module. During implementation of this useful widget, I detected some problems/issues:

1.: Under some circumstances a click to a day of a previous or next month jumps/highlighted a wrong day. It's my main problem, details see below Maybe a similar problem like described in this thread -> https://github.com/j4321/tkcalendar/issues/87

2.: "calevent" hover text isn't displayed This is already described in "https://github.com/j4321/tkcalendar/issues/43" The described workaround "...update_idletasks()" fix the problem for me.

3.: If the days of a month are displayed with the days of the previous/next month (showothermonthdays=True [=default]) and if such a day of previous/next month contains a "calevent", then this event isn't displayed. Only if one switches to the next month and then back to the previous month, this event is displayed like it should. Workaround for me is: After the calender object is created and all "calevents" are set, with "selection_set(+31 days)" the next month is selected and then immediately select the origin date (see example).

Detailed explanation to point 1

Good case: Run the example below, call the calendar.

Bad case: Run again the example below, call the calendar.

Actual I disabled the displaying of previous/next month with "showothermonthdays=False", but it would be nice and useful, if this helpful option can be used. So a fix or also a workaround for this problem is appreciated.

Regards

# -> https://tkcalendar.readthedocs.io/en/stable/example.html
try:
    import tkinter as tk
    from tkinter import ttk
except ImportError:
    import Tkinter as tk
    import ttk

from tkcalendar import Calendar, DateEntry

def example():
    Top = tk.Toplevel(root)

    ttk.Label(Top, text='Choose date').pack(padx=10, pady=10)

    # workaround (issue 2), that no "calevent" hover text is displayed
    # -> https://github.com/j4321/tkcalendar/issues/43
    Top.update_idletasks() 
    # end workaround

    Cal = Calendar(Top, selectmode='day', locale='de_DE', date_pattern="dd.mm.yyyy",
                   year=2022, month=4, day=10, tooltipdelay=500)

    EventDate   = Cal.datetime (2022, 5, 4)
    Cal.calevent_create(EventDate, 'Test Select with CalEvent', 'reminder')
    Cal.tag_config('reminder', background='red', foreground='yellow')

    # workaround (issue 3) for the problem, that initial/very first time "calevent" 
    # hover text for previous/next month are not displayed
    # -> set calendar to the next month, then back to the initial date
    InitialDate = Cal.selection_get()
    Cal.selection_set (InitialDate-Cal.timedelta(days=31))
    Cal.selection_set (InitialDate)
    # end workaround

    Cal.pack(padx=10, pady=10)

root = tk.Tk()
ttk.Button(root, text='Click on "4.05.2022" shows the problem', command=example).pack(padx=10, pady=10)

root.mainloop()
siriuskht commented 2 years ago

After digging a bit into the code, I possibly found a workaround for the problem; but it's a bit quick and dirty...

Add following marked code in calendar_.py within the module "def _on_click(self, event):"

    def _on_click(self, event):
        """Select the day on which the user clicked."""
        if self._properties['state'] == 'normal':
            label = event.widget
            if "disabled" not in label.state():
                day = label.cget("text")
                style = label.cget("style")
                if style in ['normal_om.%s.TLabel' % self._style_prefixe, 'we_om.%s.TLabel' % self._style_prefixe]:
                    if label in self._calendar[0]:
                        self._prev_month()
                    else:
                        self._next_month()

                # --------------------------------------------------------------------------------------------
                # 02.05.2022 KHT: Workaround: Problem, that "CalEvent" of previous/next month doesn't select 
                #                 the day of previous/next month, but stays in the same month
                elif day:  # day must contain a valid number 1..31
                           # in case of "showothermonthdays=False", empty days contains ""
                    # WidgetName should be "!labelXX", where XX is a number of the day labels from 10 ..  56
                    WidgetName = str(label).split(".")[-1]
                    if ((len (WidgetName) == 8) and (WidgetName[0:6] == "!label")):
                        WidgetNr = int (WidgetName[6:8])
                        if ((WidgetNr >= 10) and (WidgetNr <= 24) and (int(day) > 15)): self._prev_month()
                        if ((WidgetNr >= 42) and (WidgetNr <= 56) and (int(day) < 15)): self._next_month()
                # --------------------------------------------------------------------------------------------

                if day:
                    day = int(day)
                    year, month = self._date.year, self._date.month
                    self._remove_selection()
                    self._sel_date = self.date(year, month, day)
                    self._display_selection()
                    if self._textvariable is not None:
                        self._textvariable.set(self.format_date(self._sel_date))
                    self.event_generate("<<CalendarSelected>>")