有没有办法让日期输入日历显示在空白的日期输入字段中? (Tk日历)

Is there a way to have the date entry calendar show up in a blank Date Entry field? (Tkcalendar)

我使用的是最新版本的 Tkcalendar。只要日期输入字段为空,就不会弹出下拉列表。它抛出这个错误:

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

以下是日期输入小部件在程序中的构建方式:

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()

这是我单击下拉菜单时发生的情况。什么都没有出现,它 returns 上面的错误消息。

是否可以绕过此错误并在不输入日期值的情况下显示下拉列表?

额外说明:当日期输入字段中有日期时,日期输入工作完美。该错误仅在字段为空时出现。

问题是 dropdown 需要这个 entry 的值来生成带有日历的 window。

它似乎通常用当前日期替换 entry 中的空字符串,然后 dropdownentry.

获取当前日期

您的代码停止替换空字符串,因此其余代码出现问题。

错误显示 parse_date() 当您有空字符串时会出现问题 - 因此它需要替换此方法并检查文本是否为空并使用一些正确的日期(即当前日期)所以 dropdown 会知道在 window 中用日历生成什么。

我检查了源代码(使用 tkcalendar.__file__ 的路径),似乎 DateEntry 没有这个功能,但在 __init__ 中它设置了 self.parse_date = self._calendar.parse_date 并且它需要不同的替换方法。

它需要 运行 原来的 __init__ 以后保留以前的 self.paser_date 并将自己的功能分配给 self.parse_date.

完整的工作代码

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()