【问题标题】:Tkcalendar: Right align calendar dropdown with the DateEntryTkcalendar:将日历下拉列表与 DateEntry 右对齐
【发布时间】:2020-08-03 17:50:08
【问题描述】:

默认情况下,日历下拉列表和 DateEntry 小部件是左对齐的。在一种情况下,日历正在离开屏幕,如图所示。我们能否以某种方式将日历下拉菜单与相应的 DateEntry 小部件右对齐。

【问题讨论】:

    标签: python tkinter tkinter-layout tkcalendar


    【解决方案1】:

    可以通过重写DateEntrydrop_down() 方法来右对齐下拉菜单。下拉菜单是一个 Toplevel,位于屏幕上

    self._top_cal.geometry('+%i+%i' % (x, y))
    

    其中 (x, y) 是下拉菜单的左上角。因此,对于左对齐的下拉菜单

    x = self.winfo_rootx()  # the left side of the entry 
    

    现在要获得右对齐的下拉菜单,我们需要将 x 更改为

    x = self.winfo_rootx() + self.winfo_width() - self._top_cal.winfo_reqwidth()
    

    即(条目右侧的位置)-(下拉菜单的宽度)。

    完整代码:

    from tkcalendar import DateEntry
    import tkinter as tk
    
    class MyDateEntry(DateEntry):
        def __init__(self, master=None, align='left', **kw):
            DateEntry.__init__(self, master, **kw)
            self.align = align
    
        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())
                if self.align == 'left':  # usual DateEntry
                    x = self.winfo_rootx()
                else:  # right aligned drop-down
                    x = self.winfo_rootx() + self.winfo_width() - self._top_cal.winfo_reqwidth()
                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)
                self._top_cal.geometry('+%i+%i' % (x, y))
                self._top_cal.deiconify()
                self._calendar.focus_set()
                self._calendar.selection_set(date)
    
    
    root = tk.Tk()
    
    tk.Label(root, text='left align').grid(row=0, column=0)
    tk.Label(root, text='right align').grid(row=0, column=1)
    MyDateEntry(root).grid(row=1, column=0)
    MyDateEntry(root, align='right').grid(row=1, column=1)
    
    root.mainloop()    
    

    编辑:您还可以检测下拉菜单是否会超出屏幕并自动调整下拉位置以避免这种情况:

    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())
            h = self._top_cal.winfo_reqheight()
            w = self._top_cal.winfo_reqwidth()
            x_max = self.winfo_screenwidth()
            y_max = self.winfo_screenheight()
            # default: left-aligned drop-down below the entry
            x = self.winfo_rootx()
            y = self.winfo_rooty() + self.winfo_height()
            if x + w > x_max:  # the drop-down goes out of the screen
                # right-align the drop-down
                x += self.winfo_width() - w
            if y + h > y_max:  # the drop-down goes out of the screen
                # bottom-align the drop-down
                y -= self.winfo_height() + h
            if self.winfo_toplevel().attributes('-topmost'):
                self._top_cal.attributes('-topmost', True)
            else:
                self._top_cal.attributes('-topmost', False)
            self._top_cal.geometry('+%i+%i' % (x, y))
            self._top_cal.deiconify()
            self._calendar.focus_set()
            self._calendar.selection_set(date)
    

    请注意,当使用多台显示器时,此解决方案将无法正常工作,因为 tkinter 仅检测到一个大矩形屏幕。

    【讨论】:

    • 漂亮!像魅力一样工作。谢谢!
    • 有什么方法可以用代码弹出DateEntry吗?
    • @CoolCloud 如果 DateEntry 已关闭,则调用 .drop_down() 会打开它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    相关资源
    最近更新 更多