是否可以在 python tkcalendar 的日期中嵌入自定义文本
Is it possible to embed custom text in python tkcalendar's date
我正在通过 tkcalendar 创建班次 table。
我想让所选日期显示自己的时间table,如图所示。
是否可以通过tkcalendar提供的任何方法来实现?或者我能做到这一点的唯一方法是从零开始创建自定义日历?我浏览了 document,但几乎找不到有用的东西。
注意:我不需要工具提示(弹出文本)
tkcalendar 的方法无法在日历中的日期下方显示文本。但是,您不必从头开始,您可以创建一个继承自 Calendar
的 Agenda
class 并仅重写显示事件的方法以将它们放在当天的标签中而不是在弹出窗口中。
准确的说,需要修改3个方法:_display_days_without_othermonthdays()
、_display_days_with_othermonthdays()
和_show_event()
,代码如下。代码可能看起来很长,但与 tkcalendar 中的原始版本相比,我实际上只在每个方法中修改了几行。
from tkcalendar import Calendar
class Agenda(Calendar):
def __init__(self, master=None, **kw):
Calendar.__init__(self, master, **kw)
# change a bit the options of the labels to improve display
for i, row in enumerate(self._calendar):
for j, label in enumerate(row):
self._cal_frame.rowconfigure(i + 1, uniform=1)
self._cal_frame.columnconfigure(j + 1, uniform=1)
label.configure(justify="center", anchor="n", padding=(1, 4))
def _display_days_without_othermonthdays(self):
year, month = self._date.year, self._date.month
cal = self._cal.monthdays2calendar(year, month)
while len(cal) < 6:
cal.append([(0, i) for i in range(7)])
week_days = {i: 'normal.%s.TLabel' % self._style_prefixe for i in range(7)} # style names depending on the type of day
week_days[self['weekenddays'][0] - 1] = 'we.%s.TLabel' % self._style_prefixe
week_days[self['weekenddays'][1] - 1] = 'we.%s.TLabel' % self._style_prefixe
_, week_nb, d = self._date.isocalendar()
if d == 7 and self['firstweekday'] == 'sunday':
week_nb += 1
modulo = max(week_nb, 52)
for i_week in range(6):
if i_week == 0 or cal[i_week][0][0]:
self._week_nbs[i_week].configure(text=str((week_nb + i_week - 1) % modulo + 1))
else:
self._week_nbs[i_week].configure(text='')
for i_day in range(7):
day_number, week_day = cal[i_week][i_day]
style = week_days[i_day]
label = self._calendar[i_week][i_day]
label.state(['!disabled'])
if day_number:
txt = str(day_number)
label.configure(text=txt, style=style)
date = self.date(year, month, day_number)
if date in self._calevent_dates:
ev_ids = self._calevent_dates[date]
i = len(ev_ids) - 1
while i >= 0 and not self.calevents[ev_ids[i]]['tags']:
i -= 1
if i >= 0:
tag = self.calevents[ev_ids[i]]['tags'][-1]
label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))
# modified lines:
text = '%s\n' % day_number + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])
label.configure(text=text)
else:
label.configure(text='', style=style)
def _display_days_with_othermonthdays(self):
year, month = self._date.year, self._date.month
cal = self._cal.monthdatescalendar(year, month)
next_m = month + 1
y = year
if next_m == 13:
next_m = 1
y += 1
if len(cal) < 6:
if cal[-1][-1].month == month:
i = 0
else:
i = 1
cal.append(self._cal.monthdatescalendar(y, next_m)[i])
if len(cal) < 6:
cal.append(self._cal.monthdatescalendar(y, next_m)[i + 1])
week_days = {i: 'normal' for i in range(7)} # style names depending on the type of day
week_days[self['weekenddays'][0] - 1] = 'we'
week_days[self['weekenddays'][1] - 1] = 'we'
prev_m = (month - 2) % 12 + 1
months = {month: '.%s.TLabel' % self._style_prefixe,
next_m: '_om.%s.TLabel' % self._style_prefixe,
prev_m: '_om.%s.TLabel' % self._style_prefixe}
week_nb = cal[0][1].isocalendar()[1]
modulo = max(week_nb, 52)
for i_week in range(6):
self._week_nbs[i_week].configure(text=str((week_nb + i_week - 1) % modulo + 1))
for i_day in range(7):
style = week_days[i_day] + months[cal[i_week][i_day].month]
label = self._calendar[i_week][i_day]
label.state(['!disabled'])
txt = str(cal[i_week][i_day].day)
label.configure(text=txt, style=style)
if cal[i_week][i_day] in self._calevent_dates:
date = cal[i_week][i_day]
ev_ids = self._calevent_dates[date]
i = len(ev_ids) - 1
while i >= 0 and not self.calevents[ev_ids[i]]['tags']:
i -= 1
if i >= 0:
tag = self.calevents[ev_ids[i]]['tags'][-1]
label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))
# modified lines:
text = '%s\n' % date.day + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])
label.configure(text=text)
def _show_event(self, date):
"""Display events on date if visible."""
w, d = self._get_day_coords(date)
if w is not None:
label = self._calendar[w][d]
if not label.cget('text'):
# this is an other month's day and showothermonth is False
return
ev_ids = self._calevent_dates[date]
i = len(ev_ids) - 1
while i >= 0 and not self.calevents[ev_ids[i]]['tags']:
i -= 1
if i >= 0:
tag = self.calevents[ev_ids[i]]['tags'][-1]
label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))
# modified lines:
text = '%s\n' % date.day + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])
label.configure(text=text)
if __name__ == '__main__':
import tkinter as tk
root = tk.Tk()
root.geometry("800x500")
agenda = Agenda(root, selectmode='none')
date = agenda.datetime.today() + agenda.timedelta(days=2)
agenda.calevent_create(date, 'Hello World', 'message')
agenda.calevent_create(date, 'Reminder 2', 'reminder')
agenda.calevent_create(date + agenda.timedelta(days=-7), 'Reminder 1', 'reminder')
agenda.calevent_create(date + agenda.timedelta(days=3), 'Message', 'message')
agenda.calevent_create(date + agenda.timedelta(days=3), 'Another message', 'message')
agenda.tag_config('reminder', background='red', foreground='yellow')
agenda.pack(fill="both", expand=True)
root.mainloop()
我正在通过 tkcalendar 创建班次 table。
我想让所选日期显示自己的时间table,如图所示。
是否可以通过tkcalendar提供的任何方法来实现?或者我能做到这一点的唯一方法是从零开始创建自定义日历?我浏览了 document,但几乎找不到有用的东西。
注意:我不需要工具提示(弹出文本)
tkcalendar 的方法无法在日历中的日期下方显示文本。但是,您不必从头开始,您可以创建一个继承自 Calendar
的 Agenda
class 并仅重写显示事件的方法以将它们放在当天的标签中而不是在弹出窗口中。
准确的说,需要修改3个方法:_display_days_without_othermonthdays()
、_display_days_with_othermonthdays()
和_show_event()
,代码如下。代码可能看起来很长,但与 tkcalendar 中的原始版本相比,我实际上只在每个方法中修改了几行。
from tkcalendar import Calendar
class Agenda(Calendar):
def __init__(self, master=None, **kw):
Calendar.__init__(self, master, **kw)
# change a bit the options of the labels to improve display
for i, row in enumerate(self._calendar):
for j, label in enumerate(row):
self._cal_frame.rowconfigure(i + 1, uniform=1)
self._cal_frame.columnconfigure(j + 1, uniform=1)
label.configure(justify="center", anchor="n", padding=(1, 4))
def _display_days_without_othermonthdays(self):
year, month = self._date.year, self._date.month
cal = self._cal.monthdays2calendar(year, month)
while len(cal) < 6:
cal.append([(0, i) for i in range(7)])
week_days = {i: 'normal.%s.TLabel' % self._style_prefixe for i in range(7)} # style names depending on the type of day
week_days[self['weekenddays'][0] - 1] = 'we.%s.TLabel' % self._style_prefixe
week_days[self['weekenddays'][1] - 1] = 'we.%s.TLabel' % self._style_prefixe
_, week_nb, d = self._date.isocalendar()
if d == 7 and self['firstweekday'] == 'sunday':
week_nb += 1
modulo = max(week_nb, 52)
for i_week in range(6):
if i_week == 0 or cal[i_week][0][0]:
self._week_nbs[i_week].configure(text=str((week_nb + i_week - 1) % modulo + 1))
else:
self._week_nbs[i_week].configure(text='')
for i_day in range(7):
day_number, week_day = cal[i_week][i_day]
style = week_days[i_day]
label = self._calendar[i_week][i_day]
label.state(['!disabled'])
if day_number:
txt = str(day_number)
label.configure(text=txt, style=style)
date = self.date(year, month, day_number)
if date in self._calevent_dates:
ev_ids = self._calevent_dates[date]
i = len(ev_ids) - 1
while i >= 0 and not self.calevents[ev_ids[i]]['tags']:
i -= 1
if i >= 0:
tag = self.calevents[ev_ids[i]]['tags'][-1]
label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))
# modified lines:
text = '%s\n' % day_number + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])
label.configure(text=text)
else:
label.configure(text='', style=style)
def _display_days_with_othermonthdays(self):
year, month = self._date.year, self._date.month
cal = self._cal.monthdatescalendar(year, month)
next_m = month + 1
y = year
if next_m == 13:
next_m = 1
y += 1
if len(cal) < 6:
if cal[-1][-1].month == month:
i = 0
else:
i = 1
cal.append(self._cal.monthdatescalendar(y, next_m)[i])
if len(cal) < 6:
cal.append(self._cal.monthdatescalendar(y, next_m)[i + 1])
week_days = {i: 'normal' for i in range(7)} # style names depending on the type of day
week_days[self['weekenddays'][0] - 1] = 'we'
week_days[self['weekenddays'][1] - 1] = 'we'
prev_m = (month - 2) % 12 + 1
months = {month: '.%s.TLabel' % self._style_prefixe,
next_m: '_om.%s.TLabel' % self._style_prefixe,
prev_m: '_om.%s.TLabel' % self._style_prefixe}
week_nb = cal[0][1].isocalendar()[1]
modulo = max(week_nb, 52)
for i_week in range(6):
self._week_nbs[i_week].configure(text=str((week_nb + i_week - 1) % modulo + 1))
for i_day in range(7):
style = week_days[i_day] + months[cal[i_week][i_day].month]
label = self._calendar[i_week][i_day]
label.state(['!disabled'])
txt = str(cal[i_week][i_day].day)
label.configure(text=txt, style=style)
if cal[i_week][i_day] in self._calevent_dates:
date = cal[i_week][i_day]
ev_ids = self._calevent_dates[date]
i = len(ev_ids) - 1
while i >= 0 and not self.calevents[ev_ids[i]]['tags']:
i -= 1
if i >= 0:
tag = self.calevents[ev_ids[i]]['tags'][-1]
label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))
# modified lines:
text = '%s\n' % date.day + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])
label.configure(text=text)
def _show_event(self, date):
"""Display events on date if visible."""
w, d = self._get_day_coords(date)
if w is not None:
label = self._calendar[w][d]
if not label.cget('text'):
# this is an other month's day and showothermonth is False
return
ev_ids = self._calevent_dates[date]
i = len(ev_ids) - 1
while i >= 0 and not self.calevents[ev_ids[i]]['tags']:
i -= 1
if i >= 0:
tag = self.calevents[ev_ids[i]]['tags'][-1]
label.configure(style='tag_%s.%s.TLabel' % (tag, self._style_prefixe))
# modified lines:
text = '%s\n' % date.day + '\n'.join([self.calevents[ev]['text'] for ev in ev_ids])
label.configure(text=text)
if __name__ == '__main__':
import tkinter as tk
root = tk.Tk()
root.geometry("800x500")
agenda = Agenda(root, selectmode='none')
date = agenda.datetime.today() + agenda.timedelta(days=2)
agenda.calevent_create(date, 'Hello World', 'message')
agenda.calevent_create(date, 'Reminder 2', 'reminder')
agenda.calevent_create(date + agenda.timedelta(days=-7), 'Reminder 1', 'reminder')
agenda.calevent_create(date + agenda.timedelta(days=3), 'Message', 'message')
agenda.calevent_create(date + agenda.timedelta(days=3), 'Another message', 'message')
agenda.tag_config('reminder', background='red', foreground='yellow')
agenda.pack(fill="both", expand=True)
root.mainloop()