You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python TkCalendar DateEntry选日期时日历出屏且get_date()报错

报错原因

你的报错和重写drop_down()方法没有关系,是Tkinter的基础使用误区:

  • 所有Tkinter组件的布局方法(grid()/pack()/place())返回值都是None
  • 你写date1=MyDateEntry(root).grid(row=1, column=0)时,date1变量存储的不是日期选择器组件实例,而是grid()返回的空值,后续调用get_date()自然会触发属性不存在的报错。

你写的下拉日历自动避障逻辑本身是可用的,只需要把组件实例化和布局摆放两步代码拆开写即可。

修复后可直接运行的代码
from tkcalendar import DateEntry
from datetime import timedelta
import tkinter as tk
from tkinter import *

class MyDateEntry(DateEntry):
    def __init__(self, master=None, align='left', **kw):
        DateEntry.__init__(self, master, **kw)
        self.align = align

    def drop_down(self):
        """根据屏幕边界自动调整下拉日历位置,避免超出显示范围"""
        if self._calendar.winfo_ismapped():
            self._top_cal.withdraw()
        else:
            self._validate_date()
            date = self.parse_date(self.get())
            cal_height = self._top_cal.winfo_reqheight()
            cal_width = self._top_cal.winfo_reqwidth()
            screen_width = self.winfo_screenwidth()
            screen_height = self.winfo_screenheight()
            
            # 默认位置:输入框左对齐,下拉显示在输入框下方
            pos_x = self.winfo_rootx()
            pos_y = self.winfo_rooty() + self.winfo_height()
            
            # 右侧超出屏幕则自动右对齐
            if pos_x + cal_width > screen_width:
                pos_x += self.winfo_width() - cal_width
            # 下方超出屏幕则自动显示在输入框上方
            if pos_y + cal_height > screen_height:
                pos_y -= self.winfo_height() + cal_height
            
            # 匹配父窗口置顶状态
            self._top_cal.attributes('-topmost', self.winfo_toplevel().attributes('-topmost'))
            self._top_cal.geometry('+%i+%i' % (pos_x, pos_y))
            self._top_cal.deiconify()
            self._calendar.focus_set()
            self._calendar.selection_set(date)


if __name__ == '__main__':
    root = tk.Tk()

    tk.Label(root, text='左对齐测试').grid(row=0, column=0, padx=10, pady=5)
    tk.Label(root, text='右对齐测试').grid(row=0, column=1, padx=10, pady=5)
    
    # 注意:先创建组件实例赋值给变量,再单独调用grid布局
    date1 = MyDateEntry(root)
    date1.grid(row=1, column=0, padx=10, pady=5)
    date2 = MyDateEntry(root, align='right')
    date2.grid(row=1, column=1, padx=10, pady=5)
    
    Button(root, text='获取日期', command=lambda: print("选中日期1:", date1.get_date(), "\n选中日期2:", date2.get_date())).grid(row=2, column=0, pady=10)
    
    root.mainloop()
效果说明
  • 下拉日历会自动检测屏幕边界,右侧超出时自动左移对齐输入框右侧,下方超出时自动上移到输入框上方,不会出现显示不全的问题
  • 点击按钮可以正常获取两个日期选择器的选中值,无报错

内容的提问来源于stack exchange,提问作者Ruchi M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 04:06:20