Tkinter 中 DateEntry 的行为 Window

Behaviour of DateEntry in Tkinter Window

我有一个按钮可以将 DateEntry 小部件添加到可滚动框架。不幸的是,框架位于 window 的底部,因此添加几行后,下拉日历隐藏在任务栏后面。有什么方法可以更改它,使日历在字段上方而不是下方打开?

这是一些测试代码

from tkinter import *
from tkinter import ttk
from tkcalendar import Calendar, DateEntry

master = Tk()

global rowNumForShiftReport
rowNumForShiftReport=0
shiftDateWidgetList=[]

def myfunction(event):
    canvas2.configure(scrollregion=canvas2.bbox("all"), width=100, height=100)

def addEntry2():
    global rowNumForShiftReport


    rowNumForShiftReport = rowNumForShiftReport + 1
    shiftDateWidgetList.append(DateEntry(frame2, state='readonly', width=15))
    shiftDateWidgetList[-1].grid(row=rowNumForShiftReport, column=0)
    rowNumForShiftReport+1


master.geometry('400x400')
btn_addField2 = ttk.Button(master, text="Add Entry",command=addEntry2)
btn_addField2.grid(row=0, column=1)
#lotFrame2 = Frame(master)
actualLabelFrame=ttk.LabelFrame(master, text="Shift Report", height=300, width=300)
actualLabelFrame.grid(row=0, column=0)
canvas2 = Canvas(actualLabelFrame,width=160)
frame2 = Frame(canvas2,width=160)
frame2.bind("<Configure>", myfunction)
canvas2.create_window((0, 0), window=frame2, anchor='nw')
scrollBar2 = ttk.Scrollbar(actualLabelFrame, orient="vertical", command=canvas2.yview)
canvas2.configure(yscrollcommand=scrollBar2.set)
scrollBar2.grid(row=0, column=2, sticky=N + S)
canvas2.grid(row=0, column=1)



mainloop()

您可以通过扩展 DateEntry 并覆盖其 drop_down() 函数来实现目标,如下所示:

class MyDateEntry(DateEntry):
    def drop_down(self):
        """Display or withdraw the drop-down calendar depending on its current state."""
        if self._calendar.winfo_ismapped():
            self._top_cal.withdraw()
        else:
            self._validate_date()
            date = self.parse_date(self.get())
            x = self.winfo_rootx()
            y = self.winfo_rooty() + self.winfo_height()
            if self.winfo_toplevel().attributes('-topmost'):
                self._top_cal.attributes('-topmost', True)
            else:
                self._top_cal.attributes('-topmost', False)
            # - patch begin: make sure the drop-down calendar is visible
            if x+self._top_cal.winfo_width() > self.winfo_screenwidth():
                x = self.winfo_screenwidth() - self._top_cal.winfo_width()
            if y+self._top_cal.winfo_height() > self.winfo_screenheight()-30:
                y = self.winfo_rooty() - self._top_cal.winfo_height()
            # - patch end
            self._top_cal.geometry('+%i+%i' % (x, y))
            self._top_cal.deiconify()
            self._calendar.focus_set()
            self._calendar.selection_set(date)        

然后将代码中的所有 DateEntry(...) 替换为 MyDateEntry(...)

注意是基于tkcalendarv1.6.1.