如何以编程方式设置ttk日历

时间:2016-05-11 15:36:26

标签: python tkinter ttk

我在我的应用程序中使用this ttk calendar

我想要做的是使用datetime.date实例设置日历,这样当日历出现时,指定的日期会突出显示。

我以为我可以使用手动_show_selectiontext args来查看bbox方法。为了测试这个想法,我将这一行放在__init__方法的末尾:

self._show_selection('%02d'%16,(42,61,41,20))

我希望能突出本月16日(5月),但事实并非如此。

我在_pressed方法中运行了print text, bbox

如果有人能够对此有所了解,我会非常感激。

2 个答案:

答案 0 :(得分:0)

在__setup_selection()中,Configure事件有一个绑定。 据推测,它可以删除"选择画布"当日历 调整大小。但是,配置事件也会在日历时触发 首先映射到屏幕,这样您的预选日期就会消失 看到它。

set_day(下方)可让您以编程方式选择一天。如果小部件重新调度自身,它会回避第一个Configure事件的问题 还不可见。

更改为日历:

def __setup_selection(self, sel_bg, sel_fg):
    self._font = font.Font()
    self._canvas = canvas = tkinter.Canvas(self._calendar,
        background=sel_bg, borderwidth=0, highlightthickness=0)
    canvas.text = canvas.create_text(0, 0, fill=sel_fg, anchor='w')

    canvas.bind('<ButtonPress-1>', lambda evt: canvas.place_forget())
    #self._calendar.bind('<Configure>', lambda evt: canvas.place_forget())
    self._calendar.bind('<Configure>', self.on_configure)        
    self._calendar.bind('<ButtonPress-1>', self._pressed)

def on_configure(self, event):
    self._canvas.place_forget()
    if self._selection is not None:
        text, iid, column = self._selection
        bbox = self._calendar.bbox(iid, column)
        self._show_selection(text, bbox)

def _prev_month(self):
    """Updated calendar to show the previous month."""
    self._canvas.place_forget()
    self._selection = None #
    self._date = self._date - self.timedelta(days=1)
    self._date = self.datetime(self._date.year, self._date.month, 1)
    self._build_calendar() # reconstuct calendar

def _next_month(self):
    """Update calendar to show the next month."""
    self._canvas.place_forget()
    self._selection = None #
    year, month = self._date.year, self._date.month
    self._date = self._date + self.timedelta(
        days=calendar.monthrange(year, month)[1] + 1)
    self._date = self.datetime(self._date.year, self._date.month, 1)
    self._build_calendar() # reconstruct calendar

def set_day(self, day):
    w = self._calendar
    if not w.winfo_viewable():
        w.after(200, self.set_day, day)
        return

    text = '%02d' % day
    column = None
    for iid in self._items:
        rowvals = w.item(iid, 'values')
        try:
            column = rowvals.index(text)
        except ValueError as err:
            pass
        else:
            item = iid
            bbox = w.bbox(iid, column)
            break

    if column is not None:
        self._selection = (text, item, column)
        self._show_selection(text, bbox) 

#test
def test():
    import sys
    root = tkinter.Tk()
    root.title('Ttk Calendar')
    ttkcal = Calendar(firstweekday=calendar.SUNDAY)
    ttkcal.pack(expand=1, fill='both')

    if 'win' not in sys.platform:
        style = ttk.Style()
        style.theme_use('clam')

    ttkcal.set_day(16) #
    root.mainloop()

答案 1 :(得分:0)

在大多数情况下@Oblivion是正确的,但我希望能够使用Datetime.date对象,并且能够在需要时遍历月份和年份。一旦我改变了下面的set_day方法,一切都很完美。

def set_day(self, dt_object):
    day = dt_object.day
    w = self._calendar

    if not w.winfo_viewable():
        w.after(200, self.set_day, dt_object)
        return
    while dt_object.year < self._date.year:
        self._prev_month()
    while dt_object.year > self._date.year:
        self._next_month()
    while dt_object.month < self._date.month:
        self._prev_month()
    while dt_object.month > self._date.month:
        self._next_month()
    text = '%02d' % day
    column = None
    for iid in self._items:
        rowvals = w.item(iid, 'values')
        try:
            column = rowvals.index(text)
        except ValueError as err:
            pass
        else:
            item = iid
            bbox = w.bbox(iid, column)
            break

    if column is not None:
        self._selection = (text, item, column)
        self._show_selection(text, bbox)
    else:
        print "Column is None"