I'm using the latest version of Tkcalendar. Whenever the date entry field is blank, the dropdown doesn't pop up. It throws this error:
Traceback (most recent call last):
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\JEvans\AppData\Roaming\Python\Python39\site-packages\tkcalendar\dateentry.py", line 246, in _on_b1_press
self.drop_down()
File "C:\Users\JEvans\AppData\Roaming\Python\Python39\site-packages\tkcalendar\dateentry.py", line 331, in drop_down
date = self.parse_date(self.get())
File "C:\Users\JEvans\AppData\Roaming\Python\Python39\site-packages\tkcalendar\calendar_.py", line 1223, in parse_date
year = numbers[indexes['Y']]
IndexError: list index out of range
Here's how the date entry widget is constructed in the program:
from tkinter import *
from tkinter import ttk
from tkcalendar import *
import tkcalendar
window = Tk()
class DateEntry(tkcalendar.DateEntry):
def _validate_date(self):
if not self.get():
return True # IMPORTANT!!! Validation must return True/False otherwise it is turned off by tkinter engine
return super()._validate_date()
def test():
pass
window.geometry('500x500')
dob = DateEntry(window, date_pattern = 'mm/dd/yyyy', width = 15, background= 'gray61', foreground="white", locale='en_US')
dob.place(x = 125, y =125)
dob.bind("<<DateEntrySelected>>", test)
dob2 = DateEntry(window, date_pattern = 'mm/dd/yyyy', width = 15, background= 'gray61', foreground="white", locale='en_US')
dob2.place(x =200, y =200)
dob2.bind("<<DateEntrySelected>>", test)
window.mainloop()
Here is what happens when I click the dropdown. Nothing appears and it returns the error message above.
Is there anyway to bypass this error and have the dropdown show without entering a date value?
Extra Clarification: The date entry works perfectly when there is a date in the date entry field. The error only appears when the field is blank.
CodePudding user response:
Problem is that dropdown
needs value from this entry
to generate window with calendar.
It seems normally it replaces empty string in entry
with current date and later dropdown
gets this current date from entry
.
Your code stops replacing empty string so it makes problem with rest of code.
Error shows that parse_date()
makes problem when you have empty string - so it would need to replace this method and also check if text is empty and use some correct date (ie. current date) so dropdown
will know what to generate in window with calendar.
I checked source code (using path from tkcalendar.__file__
) and it seems DateEntry
doesn't have this function but in __init__
it sets self.parse_date = self._calendar.parse_date
and it need different method to replace it.
It needs to run original __init__
and later keep previous self.paser_date
and assign own function to self.parse_date
.
Full working code
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import ttk
import tkcalendar
import datetime
#print(tkcalendar.__file__) path to source code (skip __init__.py)
# --- classes ---
class DateEntry(tkcalendar.DateEntry):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.old_parse_date = self.parse_date
self.parse_date = self.new_parse_date
def _validate_date(self):
if not self.get():
return True
return super()._validate_date()
def new_parse_date(self, text):
print(f'parse_date: >{text}<')
if not text:
return datetime.datetime.now() # return some default date
return self.old_parse_date(text) # runs original function
# --- functions ---
def test(event):
print('test:', event)
# --- main ---
window = tk.Tk()
tk.Label(window, text='tkcalendar.DateEntry').pack(padx=5, pady=5)
dob1 = tkcalendar.DateEntry(window, date_pattern='mm/dd/yyyy', locale='en_US')
dob1.pack()
dob1.bind("<<DateEntrySelected>>", test)
tk.Label(window, text='My DateEntry').pack(padx=5, pady=5)
dob2 = DateEntry(window, date_pattern = 'mm/dd/yyyy', locale='en_US')
dob2.pack()
dob2.bind("<<DateEntrySelected>>", test)
window.mainloop()