You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

关键修改点

解决初始日期不显示问题

  1. 重新计算当前日期对应的列索引,适配firstweekday='sunday'的布局
  2. 通过天数差计算最近的允许选择的周一,替代原代码中易出错的周数计算逻辑
  3. 调用self._update_date()强制同步选中日期到输入框,确保打开日历就能看到日期

解决当前日期始终粗体问题

  1. 在日历渲染完成后,定位到当前日期的标签控件
  2. 基于原字体添加粗体属性,避免覆盖原有样式,确保无论是否选中当前日期,都保持粗体显示

内容的提问来源于stack exchange,提问作者Mike Emerson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:22:06