Python tkinter 下拉日历控件代码
tkinter下拉日历控件
网上找的不完善的Tk日历进行修改的,可以快捷的找到并返回日期。
效果如下图,上面的是控件,下面的是调用demo窗口
如下所示:
#-*-coding:utf-8-*-
importcalendar
importtkinterastk
importtkinter.fontastkFont
fromtkinterimportttk
datetime=calendar.datetime.datetime
timedelta=calendar.datetime.timedelta
classCalendar:
def__init__(s,point=None,position=None):
#point提供一个基点,来确定窗口位置
#position窗口在点的位置'ur'-右上,'ul'-左上,'ll'-左下,'lr'-右下
#s.master=tk.Tk()
s.master=tk.Toplevel()
s.master.withdraw()
fwday=calendar.SUNDAY
year=datetime.now().year
month=datetime.now().month
locale=None
sel_bg='#ecffc4'
sel_fg='#05640e'
s._date=datetime(year,month,1)
s._selection=None#设置为未选中日期
s.G_Frame=ttk.Frame(s.master)
s._cal=s.__get_calendar(locale,fwday)
s.__setup_styles()#创建自定义样式
s.__place_widgets()#pack/grid小部件
s.__config_calendar()#调整日历列和安装标记
#配置画布和正确的绑定,以选择日期。
s.__setup_selection(sel_bg,sel_fg)
#存储项ID,用于稍后插入。
s._items=[s._calendar.insert('','end',values='')for_inrange(6)]
#在当前空日历中插入日期
s._update()
s.G_Frame.pack(expand=1,fill='both')
s.master.overrideredirect(1)
s.master.update_idletasks()
width,height=s.master.winfo_reqwidth(),s.master.winfo_reqheight()
ifpointandposition:
ifposition=='ur':x,y=point[0],point[1]-height
elifposition=='lr':x,y=point[0],point[1]
elifposition=='ul':x,y=point[0]-width,point[1]-height
elifposition=='ll':x,y=point[0]-width,point[1]
else:x,y=(s.master.winfo_screenwidth()-width)/2,(s.master.winfo_screenheight()-height)/2
s.master.geometry('%dx%d+%d+%d'%(width,height,x,y))#窗口位置居中
s.master.after(300,s._main_judge)
s.master.deiconify()
s.master.focus_set()
s.master.wait_window()#这里应该使用wait_window挂起窗口,如果使用mainloop,可能会导致主程序很多错误
def__get_calendar(s,locale,fwday):
#实例化适当的日历类
iflocaleisNone:
returncalendar.TextCalendar(fwday)
else:
returncalendar.LocaleTextCalendar(fwday,locale)
def__setitem__(s,item,value):
ifitemin('year','month'):
raiseAttributeError("attribute'%s'isnotwriteable"%item)
elifitem=='selectbackground':
s._canvas['background']=value
elifitem=='selectforeground':
s._canvas.itemconfigure(s._canvas.text,item=value)
else:
s.G_Frame.__setitem__(s,item,value)
def__getitem__(s,item):
ifitemin('year','month'):
returngetattr(s._date,item)
elifitem=='selectbackground':
returns._canvas['background']
elifitem=='selectforeground':
returns._canvas.itemcget(s._canvas.text,'fill')
else:
r=ttk.tclobjs_to_py({item:ttk.Frame.__getitem__(s,item)})
returnr[item]
def__setup_styles(s):
#自定义TTK风格
style=ttk.Style(s.master)
arrow_layout=lambdadir:(
[('Button.focus',{'children':[('Button.%sarrow'%dir,None)]})]
)
style.layout('L.TButton',arrow_layout('left'))
style.layout('R.TButton',arrow_layout('right'))
def__place_widgets(s):
#标头框架及其小部件
Input_judgment_num=s.master.register(s.Input_judgment)#需要将函数包装一下,必要的
hframe=ttk.Frame(s.G_Frame)
gframe=ttk.Frame(s.G_Frame)
bframe=ttk.Frame(s.G_Frame)
hframe.pack(in_=s.G_Frame,side='top',pady=5,anchor='center')
gframe.pack(in_=s.G_Frame,fill=tk.X,pady=5)
bframe.pack(in_=s.G_Frame,side='bottom',pady=5)
lbtn=ttk.Button(hframe,style='L.TButton',command=s._prev_month)
lbtn.grid(in_=hframe,column=0,row=0,padx=12)
rbtn=ttk.Button(hframe,style='R.TButton',command=s._next_month)
rbtn.grid(in_=hframe,column=5,row=0,padx=12)
s.CB_year=ttk.Combobox(hframe,width=5,values=[str(year)foryearinrange(datetime.now().year,datetime.now().year-11,-1)],validate='key',validatecommand=(Input_judgment_num,'%P'))
s.CB_year.current(0)
s.CB_year.grid(in_=hframe,column=1,row=0)
s.CB_year.bind('',lambdaevent:s._update(event,True))
s.CB_year.bind("<>",s._update)
tk.Label(hframe,text='年',justify='left').grid(in_=hframe,column=2,row=0,padx=(0,5))
s.CB_month=ttk.Combobox(hframe,width=3,values=['%02d'%monthformonthinrange(1,13)],state='readonly')
s.CB_month.current(datetime.now().month-1)
s.CB_month.grid(in_=hframe,column=3,row=0)
s.CB_month.bind("<>",s._update)
tk.Label(hframe,text='月',justify='left').grid(in_=hframe,column=4,row=0)
#日历部件
s._calendar=ttk.Treeview(gframe,show='',selectmode='none',height=7)
s._calendar.pack(expand=1,fill='both',side='bottom',padx=5)
ttk.Button(bframe,text="确定",width=6,command=lambda:s._exit(True)).grid(row=0,column=0,sticky='ns',padx=20)
ttk.Button(bframe,text="取消",width=6,command=s._exit).grid(row=0,column=1,sticky='ne',padx=20)
tk.Frame(s.G_Frame,bg='#565656').place(x=0,y=0,relx=0,rely=0,relwidth=1,relheigh=2/200)
tk.Frame(s.G_Frame,bg='#565656').place(x=0,y=0,relx=0,rely=198/200,relwidth=1,relheigh=2/200)
tk.Frame(s.G_Frame,bg='#565656').place(x=0,y=0,relx=0,rely=0,relwidth=2/200,relheigh=1)
tk.Frame(s.G_Frame,bg='#565656').place(x=0,y=0,relx=198/200,rely=0,relwidth=2/200,relheigh=1)
def__config_calendar(s):
#cols=s._cal.formatweekheader(3).split()
cols=['日','一','二','三','四','五','六']
s._calendar['columns']=cols
s._calendar.tag_configure('header',background='grey90')
s._calendar.insert('','end',values=cols,tag='header')
#调整其列宽
font=tkFont.Font()
maxwidth=max(font.measure(col)forcolincols)
forcolincols:
s._calendar.column(col,width=maxwidth,minwidth=maxwidth,
anchor='center')
def__setup_selection(s,sel_bg,sel_fg):
def__canvas_forget(evt):
canvas.place_forget()
s._selection=None
s._font=tkFont.Font()
s._canvas=canvas=tk.Canvas(s._calendar,background=sel_bg,borderwidth=0,highlightthickness=0)
canvas.text=canvas.create_text(0,0,fill=sel_fg,anchor='w')
canvas.bind('',__canvas_forget)
s._calendar.bind('',__canvas_forget)
s._calendar.bind('',s._pressed)
def_build_calendar(s):
year,month=s._date.year,s._date.month
#updateheadertext(Month,YEAR)
header=s._cal.formatmonthname(year,month,0)
#更新日历显示的日期
cal=s._cal.monthdayscalendar(year,month)
forindx,iteminenumerate(s._items):
week=cal[indx]ifindx9999:return
s._canvas.place_forget()
s._date=datetime(year,month,1)
s._build_calendar()#重建日历
ifyear==datetime.now().yearandmonth==datetime.now().month:
day=datetime.now().day
for_item,day_listinenumerate(s._cal.monthdayscalendar(year,month)):
ifdayinday_list:
item='I00'+str(_item+2)
column='#'+str(day_list.index(day)+1)
s.master.after(100,lambda:s._pressed(item=item,column=column,widget=s._calendar))
def_exit(s,confirm=False):
"""退出窗口"""
ifnotconfirm:s._selection=None
s.master.destroy()
def_main_judge(s):
"""判断窗口是否在最顶层"""
try:
#s.master为TK窗口
#ifnots.master.focus_displayof():s._exit()
#else:s.master.after(10,s._main_judge)
#s.master为toplevel窗口
ifs.master.focus_displayof()==Noneor'toplevel'notinstr(s.master.focus_displayof()):s._exit()
else:s.master.after(10,s._main_judge)
except:
s.master.after(10,s._main_judge)
#s.master.tk_focusFollowsMouse()#焦点跟随鼠标
defselection(s):
"""返回表示当前选定日期的日期时间。"""
ifnots._selection:returnNone
year,month=s._date.year,s._date.month
returnstr(datetime(year,month,int(s._selection[0])))[:10]
defInput_judgment(s,content):
"""输入判断"""
#如果不加上==""的话,就会发现删不完。总会剩下一个数字
ifcontent.isdigit()orcontent=="":
returnTrue
else:
returnFalse
if__name__=='__main__':
root=tk.Tk()
width,height=root.winfo_reqwidth()+50,50#窗口大小
x,y=(root.winfo_screenwidth()-width)/2,(root.winfo_screenheight()-height)/2
root.geometry('%dx%d+%d+%d'%(width,height,x,y))#窗口位置居中
date_str=tk.StringVar()
date=ttk.Entry(root,textvariable=date_str)
date.place(x=0,y=0,relx=5/20,rely=1/6,relwidth=14/20,relheigh=2/3)
#Calendar((x,y),'ur').selection()获取日期,x,y为点坐标
date_str_gain=lambda:[
date_str.set(date)
fordatein[Calendar((x,y),'ur').selection()]
ifdate]
tk.Button(root,text='日期:',command=date_str_gain).place(x=0,y=0,relx=1/20,rely=1/6,relwidth=4/20,relheigh=2/3)
root.mainloop()
       
以上这篇Pythontkinter下拉日历控件代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
