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]ifindx 9999: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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。