tkcalendar仅允许选周一:初始日期框为空及日期加粗需求
tkcalendar改造问题解决方案
问题说明
基于j_4321的代码改造tkcalendar,设置仅允许用户选择周一(因首周设为周日,实际指定calendar.TUESDAY对应周一),但存在两个问题:
- 日历打开时日期框无初始日期,仅点击可选周一后才显示日期
- 当前日期无法始终以粗体显示(切换选择其他周一后,原当前日期的粗体样式消失)
修改后的完整代码
import tkinter as tk import tkcalendar as tkc import calendar from datetime import date class MyCalendar(tkc.Calendar): def __init__(self, master=None, allowed_weekdays=(calendar.MONDAY,), **kw): self._select_only = allowed_weekdays tkc.Calendar.__init__(self, master, **kw) # 适配firstweekday,计算当前选中日期对应的列索引 if self.firstweekday == 'sunday': current_wday = (self._sel_date.weekday() + 1) % 7 else: current_wday = self._sel_date.weekday() # 若当前日期不在允许范围内,调整到最近的允许日期 if self._sel_date and current_wday not in allowed_weekdays: target_wday = allowed_weekdays[0] days_diff = (target_wday - current_wday) % 7 # 选择更近的那个周几 if days_diff > 3: days_diff -= 7 sel_date = self._sel_date + tkc.dateutil.relativedelta(days=days_diff) # 设置选中日期并同步到输入框 self.selection_set(sel_date) self._update_date() def _display_calendar(self): tkc.Calendar._display_calendar(self) # 禁用非允许的日期 for i in range(6): for j in range(7): if j not in self._select_only: self._calendar[i][j].state(['disabled']) # 给当前日期设置粗体样式 today = date.today() # 确认当前日历显示的是今天所在月份 if self._date.year == today.year and self._date.month == today.month: cal_matrix = self._month_calendar for row_idx, row in enumerate(cal_matrix): if today.day in row: col_idx = row.index(today.day) # 获取原字体并添加粗体属性 font_info = self._calendar[row_idx][col_idx]['font'].split() self._calendar[row_idx][col_idx].config(font=(font_info[0], font_info[1], 'bold')) break root = tk.Tk() root.title("选择周一日期") # 首周设为周日,允许选择的是周一(对应列索引1,即calendar.TUESDAY) cal = MyCalendar(root, firstweekday='sunday', allowed_weekdays=(calendar.TUESDAY,), selectmode='day', locale='zh_CN', font='Arial 14', showweeknumbers=False, showothermonthdays=False, weekendbackground='white', weekendforeground='black', othermonthbackground='gray95', othermonthwebackground='gray95', othermonthforeground='black', othermonthweforeground='black') cal.pack() root.mainloop()
关键修改点
解决初始日期不显示问题
- 重新计算当前日期对应的列索引,适配
firstweekday='sunday'的布局 - 通过天数差计算最近的允许选择的周一,替代原代码中易出错的周数计算逻辑
- 调用
self._update_date()强制同步选中日期到输入框,确保打开日历就能看到日期
解决当前日期始终粗体问题
- 在日历渲染完成后,定位到当前日期的标签控件
- 基于原字体添加粗体属性,避免覆盖原有样式,确保无论是否选中当前日期,都保持粗体显示
内容的提问来源于stack exchange,提问作者Mike Emerson
相关产品推荐
相关产品推荐

