python tkinter日期选择器
晚上好,请完成我的请求,我正在使用Rambarun Komaljeet编写的美丽日历,我希望这样:当我单击我选择的日期时,日历关闭并将日期写入字段“data_operation”中。稍后,当我阅读dq Mysql提供的数据时,该字段必须更新。我附上代码。提前谢谢。保罗(意大利巴里)python tkinter日期选择器,python,tkinter,datepicker,Python,Tkinter,Datepicker,晚上好,请完成我的请求,我正在使用Rambarun Komaljeet编写的美丽日历,我希望这样:当我单击我选择的日期时,日历关闭并将日期写入字段“data_operation”中。稍后,当我阅读dq Mysql提供的数据时,该字段必须更新。我附上代码。提前谢谢。保罗(意大利巴里) #/usr/bin/env python #-*-编码:utf-8-*- #作者:Rambarun Komaljeet #许可证:LGPL # ------------------------------------
#/usr/bin/env python
#-*-编码:utf-8-*-
#作者:Rambarun Komaljeet
#许可证:LGPL
# ---------------------------------------------------------------------
导入日历
将tkinter作为tk导入
导入时间
从tkinter导入ttk
类MyDatePicker(tk.Toplevel):
"""
说明:
tkinter GUI日期选择器。
"""
def uuu init uuu(self,parent=None):
"""
说明:
在父模块/widget/Gui中实例化时,将“self”作为参数传入。
前任:
a=MyDatePicker(自)
:param parent:父实例。
"""
super()。\uuuu init\uuuuu()
self.parent=parent
自我名称(“日期选择器”)
可自行调整大小(0,0)
自身几何(“250+10”)
self.init_frames()
self.init_needed_vars()
self.init\u月\u年\u标签()
self.init_按钮()
self.space_在_小部件之间()
self.fill_天()
self.make_日历()
def初始帧(自):
self.frame1=tk.Frame(self)
self.frame1.pack()
self.frame_days=tk.frame(self)
self.frame_days.pack()
def初始所需变量(自身):
self.month\u name=元组(calendar.month\u name)
self.day\u name=元组(calendar.day\u缩写)
self.year=time.strftime(“%Y”)
self.month=time.strftime(“%B”)
def初始月/年标签(自身):
self.year\u str\u var=tk.StringVar()
self.month\u str\u var=tk.StringVar()
self.year\u str\u var.set(self.year)
self.year\u lbl=tk.Label(self.frame1,textvariable=self.year\u str\u var,width=3)
自年网格(行=0,列=5)
self.month\u str\u var.set(self.month)
self.month\u lbl=tk.Label(self.frame1,textvariable=self.month\u str\u var,宽度=8)
自我月平衡网格(行=0,列=1)
def初始按钮(自身):
self.left_yr=ttk.Button(self.frame1,text=”←", 宽度=5,命令=self.prev_年)
自左网格(行=0,列=4)
self.right_yr=ttk.Button(self.frame1,text=”→,宽度=5,命令=self。下一年)
自右年网格(行=0,列=6)
self.left\u mon=ttk.Button(self.frame1,text=”←,宽度=5,命令=self.prev_月)
自左单网格(行=0,列=0)
self.right\u mon=ttk.Button(self.frame1,text=”→,宽度=5,命令=self.下个月)
自右单网格(行=0,列=2)
定义小部件之间的空间(self):
self.frame1.grid\u columnconfigure(3,minsize=40)
def上一年(自我):
self.prev\u yr=int(self.year\u str\u var.get())-1
自年结构变量集(自上一年)
self.make_日历()
def下一年(自我):
self.next\u yr=int(self.year\u str\u var.get())+1
自年结构变量集(自下一年)
self.make_日历()
def上个月(自我):
index\u current\u month=int(self.month\u names.index(self.month\u str\u var.get())
指数上个月=指数当前月-1
#索引0是空字符串,请改用索引12,它是12月份的索引。
如果指数上个月=0:
self.month\u str\u var.set(self.month\u名称[12])
其他:
self.month\u str\u var.set(self.month\u名称[索引\u当前\u月-1])
self.make_日历()
def下个月(自我):
index\u current\u month=int(self.month\u names.index(self.month\u str\u var.get())
#索引13不存在,请使用索引1,即1月份。
尝试:
self.month\u str\u var.set(self.month\u名称[索引\u当前\u月+1])
除索引器外:
self.month\u str\u var.set(self.month\u名称[1])
self.make_日历()
def加注天数(自我):
col=0
#创建天数标签
以self.day_名称表示的日期:
self.lbl\u day=tk.Label(self.frame\u days,text=day)
self.lbl_day.grid(行=0,列=col)
col+=1
def make_日历(自):
#删除日期按钮(如果已存在)。
#每个按钮都必须有自己的实例属性才能工作。
尝试:
对于self.m_cal中的日期:
对于日期中的日期:
如果日期==0:
持续
self.delete_按钮(日期)
除属性错误外:
通过
year=int(self.year\u str\u var.get())
month=self.month\u names.index(self.month\u str\u var.get())
self.m_cal=日历.月日历(年,月)
#构建日期按钮。
对于self.m_cal中的日期:
行=自校准索引(日期)+1
对于日期中的日期:
col=日期。索引(日期)
如果日期==0:
持续
自制按钮(str(日期)、str(行)、str(列))
def make_按钮(自身、日期、行、列):
执行官(
“self.btn”+date+”=ttk.按钮(self.frame\u天,text=“+date+”,width=5)\n”
“self.btn_”+date+”.grid(row=“+row+”,column=“+column+”)\n”
self.btn\+date+.bind(\“\”,self.get\'date)
)
def delete_按钮(自身、日期):
执行官(
“self.btn_”+str(日期)+.destroy()”
)
def get_日期(自,单击=无):
全球数据运营商
clicked_button=clicked.widget
year=self.year\u str\u var.get()
month=self.month\u names.index(self.month\u str\u var.get())
日期=点击按钮['text']
#更改不同日期格式的字符串格式。
self.full_日期=“%s-%02d-%02d%”(年、月、日)
打印(自身完整日期)
#插入日期
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Rambarun Komaljeet
# License: LGPL
# ---------------------------------------------------------------------
import calendar
import tkinter as tk
import time
from tkinter import ttk
class MyDatePicker(tk.Toplevel):
"""
Description:
A tkinter GUI date picker.
"""
def __init__(self, parent=None):
"""
Description:
When instantiating in parent module/widget/Gui, pass in 'self' as argument.
Ex:
a = MyDatePicker(self)
:param parent: parent instance.
"""
super().__init__()
self.parent = parent
self.title("Date Picker")
self.resizable(0, 0)
self.geometry("+250+10")
self.init_frames()
self.init_needed_vars()
self.init_month_year_labels()
self.init_buttons()
self.space_between_widgets()
self.fill_days()
self.make_calendar()
def init_frames(self):
self.frame1 = tk.Frame(self)
self.frame1.pack()
self.frame_days = tk.Frame(self)
self.frame_days.pack()
def init_needed_vars(self):
self.month_names = tuple(calendar.month_name)
self.day_names = tuple(calendar.day_abbr)
self.year = time.strftime("%Y")
self.month = time.strftime("%B")
def init_month_year_labels(self):
self.year_str_var = tk.StringVar()
self.month_str_var = tk.StringVar()
self.year_str_var.set(self.year)
self.year_lbl = tk.Label(self.frame1, textvariable=self.year_str_var, width=3)
self.year_lbl.grid(row=0, column=5)
self.month_str_var.set(self.month)
self.month_lbl = tk.Label(self.frame1, textvariable=self.month_str_var, width=8)
self.month_lbl.grid(row=0, column=1)
def init_buttons(self):
self.left_yr = ttk.Button(self.frame1, text="←", width=5, command=self.prev_year)
self.left_yr.grid(row=0, column=4)
self.right_yr = ttk.Button(self.frame1, text="→", width=5, command=self.next_year)
self.right_yr.grid(row=0, column=6)
self.left_mon = ttk.Button(self.frame1, text="←", width=5, command=self.prev_month)
self.left_mon.grid(row=0, column=0)
self.right_mon = ttk.Button(self.frame1, text="→", width=5, command=self.next_month)
self.right_mon.grid(row=0, column=2)
def space_between_widgets(self):
self.frame1.grid_columnconfigure(3, minsize=40)
def prev_year(self):
self.prev_yr = int(self.year_str_var.get()) - 1
self.year_str_var.set(self.prev_yr)
self.make_calendar()
def next_year(self):
self.next_yr = int(self.year_str_var.get()) + 1
self.year_str_var.set(self.next_yr)
self.make_calendar()
def prev_month(self):
index_current_month = int(self.month_names.index(self.month_str_var.get()))
index_prev_month = index_current_month - 1
# index 0 is empty string, use index 12 instead, which is index of December.
if index_prev_month == 0:
self.month_str_var.set(self.month_names[12])
else:
self.month_str_var.set(self.month_names[index_current_month - 1])
self.make_calendar()
def next_month(self):
index_current_month = int(self.month_names.index(self.month_str_var.get()))
# index 13 does not exist, use index 1 instead, which is January.
try:
self.month_str_var.set(self.month_names[index_current_month + 1])
except IndexError:
self.month_str_var.set(self.month_names[1])
self.make_calendar()
def fill_days(self):
col = 0
# Creates days label
for day in self.day_names:
self.lbl_day = tk.Label(self.frame_days, text=day)
self.lbl_day.grid(row=0, column=col)
col += 1
def make_calendar(self):
# Delete date buttons if already present.
# Each button must have its own instance attribute for this to work.
try:
for dates in self.m_cal:
for date in dates:
if date == 0:
continue
self.delete_buttons(date)
except AttributeError:
pass
year = int(self.year_str_var.get())
month = self.month_names.index(self.month_str_var.get())
self.m_cal = calendar.monthcalendar(year, month)
# build date buttons.
for dates in self.m_cal:
row = self.m_cal.index(dates) + 1
for date in dates:
col = dates.index(date)
if date == 0:
continue
self.make_button(str(date), str(row), str(col))
def make_button(self, date, row, column):
exec(
"self.btn_" + date + "= ttk.Button(self.frame_days, text=" + date + ", width=5)\n"
"self.btn_" + date + ".grid(row=" + row + " , column=" + column + ")\n"
"self.btn_" + date + ".bind(\"<Button-1>\", self.get_date)"
)
def delete_buttons(self, date):
exec(
"self.btn_" + str(date) + ".destroy()"
)
def get_date(self, clicked=None):
global DATA_OPERAZIONE
clicked_button = clicked.widget
year = self.year_str_var.get()
month = self.month_names.index(self.month_str_var.get())
date = clicked_button['text']
# Change string format for different date formats.
self.full_date = '%s-%02d-%02d' % (year, month, date)
print(self.full_date)
# insert date in parent widget like these:
# in parent:
# self.a = tk.StringVar()
# self.parent.a.set(self.full_date)
#
# if a is tk.Entry:
# self.parent.a.insert(0, self.full_date)
#DATA_OPERAZIONE = self.full_date
#print('data mia', DATA_OPERAZIONE )
if __name__ == '__main__':
def application():
app = MyDatePicker()
return DATA_OPERAZIONE
root = tk.Tk()
btn = tk.Button(root, text="test", command=application)
btn.pack()
# Data Operazione
DATA_OPERAZIONE = tk.StringVar()
data_operazione_lbl = tk.Label(root, text="Data Operazione", font=
`enter code here`('arial', 8), bd=10)
data_operazione_lbl.pack()
data_operazione = tk.Entry(root, textvariable=DATA_OPERAZIONE, width=10)
data_operazione.pack()
root.mainloop()
data_operazione.delete (0, tk.END)
data_operazione.insert (0, self.full_date)
self.destroy ()
import calendar, datetime
from tkinter import *
class Calendar (Canvas):
# Create the widget
def __init__ (self, root, *cnf, **kw):
"""
Construct a calendar widget with all the canvas functionality.
Key words are listed in the config function's help.
"""
try:
self.levels = kw ["levels"]
del kw ["levels"]
except:
try:
self.levels = kw ["Levels"]
del kw ["Levels"]
except: self.levels = 3
try:
self.close = kw ["close_action"]
del kw ["close_action"]
except:
try:
self.close = kw ["Close_action"]
del kw ["Close_action"]
except:
try:
self.close = kw ["close_Action"]
del kw ["close_Action"]
except:
try:
self.close = kw ["Close_Action"]
del kw ["Close_Action"]
except: self.close = 2
self.sup, self.cur, self.root, self.cal, self.year, self.month, self.level, self.added, self.end = super (Calendar, self), [0, 0, 1, datetime.date.today().year, datetime.date.today().month], root, calendar.TextCalendar (), datetime.date.today().year, datetime.date.today().month, 2 if self.levels > 1 else 3, 0, False
self.sup.__init__ (root, *cnf, **kw)
self.rect = self.create_rectangle (0, 0, 0, 0)
self.bind ("<Configure>", lambda event: self.__setup ())
self.root.bind ("<Up>", lambda event: self.__upLevel ())
self.root.bind ("<Down>", lambda event: self.__downLevel ())
self.root.bind ("<Right>", lambda event: self.__down ())
self.root.bind ("<Left>", lambda event: self.__up ())
# Give the user an option to reconfigure the calendar
def config (self, **kw):
"""
Configure the calendar widget.
Key words that are not standard for a tkinter canvas are listed below:
levels=
Allowed user accuracy of the calendar.
1 = Month
2 = Day
3 = 10 minutes
The default is 3.
(levels/Levels)
close_action=
What happens when user clicks the 'OK' button.
1 = Remove from the window
2 = Disable the calendar
The default is 2.
(close_action/Close_action/close_Action/Close_Action)
"""
try:
self.levels = kw ["levels"]
del kw ["levels"]
except:
try:
self.levels = kw ["Levels"]
del kw ["Levels"]
except: pass
try:
self.close = kw ["close_action"]
del kw ["close_action"]
except:
try:
self.close = kw ["Close_action"]
del kw ["Close_action"]
except:
try:
self.close = kw ["close_Action"]
del kw ["close_Action"]
except:
try:
self.close = kw ["Close_Action"]
del kw ["Close_Action"]
except: pass
if 4 - self.levels > self.level: self.level = 4 - self.levels
self.sup.config (**kw)
self.__setup ()
# Draw the calendar on the canvas
def __setup (self):
self.root.update ()
width, height = self.winfo_width (), self.winfo_height ()
if height < 80: height = 80
if width < 120: width = 120
self.delete (ALL)
if self.level != 3:
a = [self.create_polygon ((40, 0), (width - 40, 0), (width - 20, 20), (20, 20), fill = "red", outline = "black"),
self.create_line (int (width / 2) - 10, 15, int (width / 2), 5, width = 2),
self.create_line (int (width / 2) + 10, 15, int (width / 2), 5, width = 2)]
for i in a: self.tag_bind (i, "<Button-1>", lambda event: self.__upLevel ())
if self.level != 4 - self.levels:
a = [self.create_polygon ((40, height), (width - 40, height), (width - 20, height - 20), (20, height - 20), fill = "red", outline = "black"),
self.create_line (int (width / 2) - 10, height - 15, int (width / 2), height - 5, width = 2),
self.create_line (int (width / 2) + 10, height - 15, int (width / 2), height - 5, width = 2)]
for i in a: self.tag_bind (i, "<Button-1>", lambda event: self.__downLevel ())
a = [self.create_polygon ((0, 40), (20, 20), (20, height - 20), (0, height - 40), fill = "red", outline = "black"),
self.create_line (15, int (height / 2) - 10, 5, int (height / 2), width = 2),
self.create_line (15, int (height / 2) + 10, 5, int (height / 2), width = 2)]
for i in a: self.tag_bind (i, "<Button-1>", lambda event: self.__up ())
a = [self.create_polygon ((width, 40), (width - 20, 20), (width - 20, height - 20), (width, height - 40), fill = "red", outline = "black"),
self.create_line (width - 15, int (height / 2) - 10, width - 5, int (height / 2), width = 2),
self.create_line (width - 15, int (height / 2) + 10, width - 5, int (height / 2), width = 2)]
for i in a: self.tag_bind (i, "<Button-1>", lambda event: self.__down ())
a = [self.create_polygon ((35, height - 20), (width - 35, height - 20), (width - 55, height - 40), (55, height - 40), fill = "red", outline = "black"),
self.create_text (int (width / 2), height - 30, text = "OK")]
for i in a: self.tag_bind (i, "<Button-1>", lambda event: self.__ok ())
if self.level == 3:
if width - 40 < height - 80: self.height, self.width = (width - 40) / 4, (width - 40) / 3
else: self.width, self.height = (height - 80) / 3, (height - 80) / 4
self.create_text (int (width / 2), 30, text = str (self.cur [3]))
font = ("Courier New", int (self.height * 0.45 - 1))
if font [1] < 1: font = ("Courier New", 1)
for y in range (4):
for x in range (3):
b = [self.create_rectangle (x * self.width + 20, y * self.height + 40, x * self.width + self.width + 20, y * self.height + self.height + 40, fill = "white"),
self.create_text (x * self.width + (self.width / 2) + 20, y * self.height + (self.height / 2) + 40, text = calendar.month_abbr [y * 3 + x + 1], font = font)]
for i in b: self.tag_bind (i, "<Button-1>", lambda event, x = x, y = y: self.__click (y, x, None))
if y * 3 + x + 1 == self.cur [4]: self.__click (y, x, None)
elif self.level == 2:
self.rows = len (self.cal.monthdayscalendar (*self.cur [3 : ]))
if width - 40 < height - 80: self.height, self.width = (width - 40) / self.rows, (width - 40) / 7
else: self.width, self.height = (height - 80) / 7, (height - 80) / self.rows
font = ("Courier New", int (self.height * 0.45))
self.create_text (int (width / 2), 30, text = calendar.month_name [self.cur [4]] + " " + str (self.cur [3]))
if font [1] < 1: font = ("Courier New", 1)
for w, week in enumerate (self.cal.monthdayscalendar (*self.cur [3 : ])):
for d, day in enumerate (week):
if day:
b = [self.create_rectangle (d * self.width + 20, w * self.height + 40, d * self.width + self.width + 20, w * self.height + self.height + 40, fill = "white"),
self.create_text (d * self.width + (self.width / 2) + 20, w * self.height + (self.height / 2) + 40, text = day, font = font)]
for i in b: self.tag_bind (i, "<Button-1>", lambda event, w = w, d = d, day = day: self.__click (w, d, day))
if day == self.cur [2]: self.__click (w, d, day)
else:
if width - 40 < height - 80: self.height, self.width = (width - 40) / 24, (width - 40) / 6
else: self.width, self.height = (height - 80) / 6, (height - 80) / 24
font = ("Courier New", int (self.height * 0.45 - 1))
self.create_text (int (width / 2), 30, text = "%s %s %s" % (self.__dayToPosition (self.cur [2]), calendar.month_name [self.cur [4]], str (self.cur [3])))
if font [1] < 1: font = ("Courier New", 1)
for h in range (24):
for m in range (0, 6):
b = [self.create_rectangle (m * self.width + 20, h * self.height + 40, m * self.width + self.width + 20, h * self.height + self.height + 40, fill = "white"),
self.create_text (m * self.width + (self.width / 2) + 20, h * self.height + (self.height / 2) + 40, text = "%s:%s" % (h if h >= 10 else "0" + str (h), m * 10 if m > 0 else "00"), font = font)]
for i in b: self.tag_bind (i, "<Button-1>", lambda event, h = h, m = m: self.__click (h, m, None))
if h == self.cur [1] and m * 10 == self.cur [0]: self.__click (h, m , None)
if self.end:
self.tag_bind (ALL, "<Button-1>", lambda event: None)
self.create_rectangle (0, 0, width, height, fill = "black", stipple = "gray50")
# Format and return the selected date (and time)
def get (self):
"""
Get the day selected by the user
"""
cur = self.cur
a = cur [4]
cur [4] = cur [3]
cur [3] = a
cur.insert (3, calendar.month_abbr [a])
cur.insert (2, calendar.day_abbr [datetime.datetime (cur [5], cur [4], cur [2]).weekday ()])
cur [0] = "%s:%s" % (cur [1] if cur [1] >= 10 else "0" + str (cur [1]), cur [0] if cur [0] >= 10 else "0" + str (cur [0]))
del cur [1]
return cur [6 - self.levels * 2 : ]
# Handle the mouse clicks
def __click (self, w, d, day):
self.delete (self.rect)
self.rect = self.create_rectangle (d * self.width + 21, w * self.height + 41, d * self.width + self.width + 20, w * self.height + self.height + 40, fill = "red", stipple = "gray25", width = 0),
if self.level == 3: self.cur = [self.cur [0], self.cur [1], self.cur [2], self.cur [3], w * 3 + d + 1]
elif self.level == 2: self.cur = [self.cur [0], self.cur [1], day, self.cur [3], self.cur [4]]
else: self.cur = [d * 10, w, self.cur [2], self.cur [3], self.cur [4]]
# Move the calendar
def __up (self):
if self.level == 3: self.cur [3] -= 1
elif self.level == 2:
self.cur [4] -= 1
if self.cur [4] < 1: self.cur = [self.cur [0], self.cur [1], self.cur [2], self.cur [3] - 1, 12]
else:
self.cur [2] -= 1
if self.cur [2] < 1: self.cur = [self.cur [0], self.cur [1], calendar.monthrange (self.cur [3], self.cur [4] - 1 if self.cur [4] - 1 > 0 else 12) [1], self.cur [3], self.cur [4] - 1]
if self.cur [4] < 1: self.cur = [self.cur [0], self.cur [1], self.cur [2], self.cur [3] - 1, 12]
self.__setup ()
def __down (self):
if self.level == 3: self.cur [3] += 1
elif self.level == 2:
self.cur [4] += 1
if self.cur [4] > 12: self.cur = [self.cur [0], self.cur [1], self.cur [2], self.cur [3] + 1, 1]
else:
self.cur [2] += 1
if self.cur [2] > calendar.monthrange (self.cur [3], self.cur [4]) [1]: self.cur = [self.cur [0], self.cur [1], 1, self.cur [3], self.cur [4] + 1]
if self.cur [4] > 12: self.cur = [self.cur [0], self.cur [1], self.cur [2], self.cur [3] + 1, 1]
self.__setup ()
# Move calendar level
def __upLevel (self):
if self.level < 3:
self.level += 1
self.__setup ()
def __downLevel (self, release = False):
if self.level > 4 - self.levels:
self.level -= 1
self.__setup ()
# Format a number to named position (e.g. 1 -> 1st)
def __dayToPosition (self, num):
if num > 9 and str(num) [-2] == '1': return str (num) + 'th'
lastDigit = num % 10
if (lastDigit == 1): return str (num) + 'st'
elif (lastDigit == 2): return str (num) + 'nd'
elif (lastDigit == 3): return str (num) + 'rd'
else: return str (num) + 'th'
# Handle when the user clicks ok
def __ok (self):
if self.close == 1:
if self.added == 1: self.pack_remove ()
elif self.added == 2: self.grid_remove ()
elif self.added == 3: self.place_remove ()
elif self.added == 2:
self.end = True
self.__setup ()
# The demonstration method
def demo ():
"""
This method is a demostration of the widget. It creates it's own 'Tk' app to put it on.
"""
root = Tk ()
root.title ("Calendar Demo")
c = Calendar (root)
c.grid (sticky = "nsew")
#help (Calendar)
root.mainloop ()
print (c.get ())
# Configure the geometry managers
def pack (self, *cnf, **kw):
self.added = 1
self.sup.pack (*cnf, **kw)
self.__setup ()
def pack_configure (self, *cnf, **kw):
self.sup.pack_configure (*cnf, **kw)
self.__setup ()
def grid (self, *cnf, **kw):
self.sup.grid (*cnf, **kw)
coords, self.added = [(child.grid_info () ["column"], child.grid_info () ["row"]) for child in self.root.children.values () if child == self] [0], 2
try: [Grid.columnconfigure (self.root, coords [0] + x, weight = 1) for x in range (kw ["columnspan"])]
except KeyError: Grid.columnconfigure (self.root, coords [0], weight = 1)
try: [Grid.rowconfigure (self.root, coords [1] + y, weight = 1) for y in range (kw ["rowspan"])]
except KeyError: Grid.rowconfigure (self.root, coords [1], weight = 1)
self.__setup ()
def grid_configure (self, *cnf, **kw):
self.sup.grid_configure (*cnf, **kw)
self.__setup ()
def place (self, *cnf, **kw):
self.added = 3
self.sup.place (*cnf, **kw)
self.__setup ()
def place_configure (self, *cnf, **kw):
self.sup.place_configure (*cnf, **kw)
self.__setup ()
if __name__ == "__main__": Calendar.demo ()
#Abhinandan
import sys
import datetime
import calendar
from functools import partial
from ui.entrymaxlength import DateIntegerEntry
import os
import platform
try:
import tkinter as tk
from tkinter import Widget
except ImportError:
import Tkinter as tk
from tkinter import Widget
try:
from tkinter import font as tkf
except ImportError:
import tkFont as tkf
try:
from tkinter import ttk
except ImportError:
import ttk
try:
import babel
import babel.dates
import babel.numbers
except ImportError:
babel = None
DEFAULT_FONT = ('TkTextFont',)
DEFAULT_FONT='Times 12'
#DEFAULT_FONT=("Calibri",14)
class TargetShape():
"""How to draw the target round a date"""
Square = 'square'
Rectangle = 'rectangle'
Circle = 'circle'
class DateEntry(tk.Frame, object):
"""A date entry widget
Creates a frame which contains entry boxes for Year, Month and Day and a
button to display a date selection dialog.
Dates will always consist of a 4 digit year and 2 digit months and days
only the order and separator are determined by the `locale` parameter
:param master: The master frame
:type master: :class:`ttk.Frame`
:param start_date: The date to display in the entry boxes
:type start_date: :class:`datetime.date` or :class:`datetime.datetime`
:param locale: Determines the order of the widgets in the entry.
Either a locale name e.g. 'en' or a babel Locale
instance. If :mod:`babel` is not installed ISO 8601
format will be used.
:type locale: str
:param font: Tk font to use. Default TkTextFont
:type font: tuple
"""
start_date=None
def __init__(self, master,
start_date=None,state=None,separator='-',
locale='en',bg='white',
font=DEFAULT_FONT, frame_look={}, **look):
args = dict(relief=tk.SUNKEN, border=1)
args.update(frame_look)
super(DateEntry, self,).__init__(master,bg=bg, **args )#style='tks.TFrame')
args = {'relief': tk.FLAT,'border':0}
args.update(look)
if babel and locale:
if not isinstance(locale, babel.Locale):
locale = babel.Locale(locale)
pattern = locale.date_formats['short'].pattern
for ch in pattern:
if ch.lower() not in ['d', 'm', 'y']:
separator = ch
break
elems = pattern.split(separator)
for idx, elem in enumerate(elems):
if 'y' in elem:
year_column = idx
elif 'M' in elem:
month_column = idx
elif 'd' in elem:
day_column = idx
else:
day_column = 0
month_column = 1
year_column = 2
separator = separator
self._locale = locale
self._font = tkf.Font(font=font)
self.day_entry=None
self.month_entry=None
self.year_entry=None
self._year_var = tk.IntVar()
self._month_var = tk.IntVar()
self._day_var = tk.IntVar()
self._time = None
self.day_entry = DateIntegerEntry(self,maxvalue=31,
maxlength=2,textvariable=self._day_var,bg=bg,justify=tk.RIGHT,
width=2,
font=self._font,state=state,**args)
self.day_entry.grid(row=0, column=day_column * 2)
self.day_entry.bind('<KeyRelease>',self.checkFocusNext)
#self._day_var.set('%d' % self.date.day)
self.month_entry = DateIntegerEntry(self,maxlength=2,maxvalue=12,
textvariable=self._month_var,bg=bg,justify=tk.RIGHT,
width=2,
font=self._font,state=state,**args)
self.month_entry.grid(row=0, column=month_column * 2)
self.month_entry.bind('<KeyRelease>',self.checkFocusNext)
'''self.day_entry = ttk.Combobox(self,
textvariable=self._day_var,
width=3,
font=self._font,state=state)
self._update_day_values(self.date.year,
self.date.month,
self.date.day)
self.day_entry.grid(row=0, column=day_column * 2)
self.month_entry = ttk.Combobox(self,
textvariable=self._month_var,
width=3,
font=self._font,state=state)
self.month_entry['values'] = ['%d' % (x + 1) for x in range(12)]
self._month_var.set('%d' % self.date.month)
self.month_entry.grid(row=0, column=month_column * 2)
self.month_entry.bind('<<ComboboxSelected>>', self._month_updated)
'''
self.month_entry.bind('<FocusOut>', self._month_updated)
#self._year_var.set(self.date.year)
self.year_entry = DateIntegerEntry(self,maxlength=4,maxvalue=9999,
textvariable=self._year_var,justify=tk.RIGHT,
width=4,
font=self._font,bg=bg,state=state,**args)
#self._year_var.set(1111)
self.year_entry.grid(row=0, column=year_column * 2)
self.year_entry.bind('<KeyRelease>',self.checkFocusNext)
self.year_entry.bind('<FocusOut>',self._month_updated)
self.lbl1 = tk.Label(self, text=separator,bg='white',**args)
self.lbl1.grid(row=0, column=1)
self.lbl2 = tk.Label(self, text=separator,bg='white' ,**args)
self.lbl2.grid(row=0, column=3)
self.day_entry.bind('<Return>', self.focusNext)
self.month_entry.bind('<Return>', self.focusNext)
self.year_entry.bind('<Return>', self.focusNext)
self.day_entry.bind('<Right>',self.next1)
self.month_entry.bind('<Right>', self.next1)
self.year_entry.bind('<Right>', self.next1)
self.day_entry.bind('<Left>',self.prev)
self.month_entry.bind('<Left>', self.prev)
self.year_entry.bind('<Left>', self.prev)
self.day_entry.bind('<Up>',self.checkUp)
self.day_entry.bind('<Down>',self.checkDown)
self.month_entry.bind('<Up>',self.checkUp)
self.month_entry.bind('<Down>',self.checkDown)
self.year_entry.bind('<Up>',self.checkUp)
self.year_entry.bind('<Down>',self.checkDown)
self.day_entry.bind('<FocusIn>',self.setFocus)
self.month_entry.bind('<FocusIn>',self.setFocus)
self.year_entry.bind('<FocusIn>',self.setFocus)
if platform.system()=='Linux':
self.day_entry.bind('<Shift-ISO_Left_Tab>',self.focusPrev)
self.month_entry.bind('<Shift-ISO_Left_Tab>',self.focusPrev)
self.year_entry.bind('<Shift-ISO_Left_Tab>',self.focusPrev)
else:
self.day_entry.bind('<Shift-Tab>',self.focusPrev)
self.month_entry.bind('<Shift-Tab>',self.focusPrev)
self.year_entry.bind('<Shift-Tab>',self.focusPrev)
self.day_entry.bind('<Tab>',self.focusNext)
self.month_entry.bind('<Tab>',self.focusNext)
self.year_entry.bind('<Tab>',self.focusNext)
self.start_date=start_date
if start_date is None:
self.date = datetime.date.today()
else:
self.date = start_date #btn = ttk.Button(self, text=_('Select...'), command=self._select_date)
#btn.grid(row=0, column=5, sticky=tk.E, padx=(6, 0))
for idx in range(5):
self.columnconfigure(idx, weight=0)
#self.day_entry.focus()
#self.columnconfigure(5, weight=1)
self.day_entry.bind('<FocusOut>',self.checkDate)
self.month_entry.bind('<FocusOut>',self.checkDate)
self.year_entry.bind('<FocusOut>',self.checkDate)
def focusNext(self,event=None):
#print('next')
#event.widget.tk_focusPrev().focus()
if event.widget.tk_focusNext().winfo_parent()==event.widget.winfo_parent() :
if event.widget.tk_focusNext().winfo_parent()==event.widget.tk_focusNext().tk_focusNext().winfo_parent():
#event.widget.tk_focusNext().focus()
event.widget.tk_focusNext().tk_focusNext().tk_focusNext().focus()
return("break")
else:
event.widget.tk_focusNext().tk_focusNext().focus()
return("break")
else:
event.widget.tk_focusNext().focus()
return("break")
def focusPrev(self,event=None):
#print('prev')
if event.widget.tk_focusPrev().winfo_parent()==event.widget.winfo_parent() :
if event.widget.tk_focusPrev().winfo_parent()==event.widget.tk_focusPrev().tk_focusPrev().winfo_parent():
event.widget.tk_focusPrev().tk_focusPrev().tk_focusPrev().focus()
return("break")
else:
event.widget.tk_focusPrev().tk_focusPrev().focus()
return("break")
else:
event.widget.tk_focusPrev().focus()
def setFocus(self,event=None):
event.widget.selection_range(0,tk.END)
def checkUp(self,event):
value=event.widget.get()
if len(value)>0:
value=int(value)+1
event.widget.delete(0,tk.END)
if len(str(value))==1:
value='0'+str(value)
event.widget.insert(0,value)
if len(event.widget.get())==0:
event.widget.insert(0,'01')
event.widget.selection_range(0,tk.END)
else:
event.widget.insert(0,'01')
return("break")
def checkDown(self,event):
value=event.widget.get()
if len(value)>0:
value=int(value)-1
event.widget.delete(0,tk.END)
if value!=0:
if len(str(value))==1:
value='0'+str(value)
event.widget.insert(0,value)
else:
event.widget.insert(0,"01")
if len(event.widget.get())==0:
event.widget.insert(0,event.widget.getMaxvalue())
event.widget.selection_range(0,tk.END)
else:
event.widget.insert(0,'01')
return("break")
def prev(self,event):
if event.widget.selection_present()==True:
if event.widget.tk_focusPrev().winfo_parent()==event.widget.winfo_parent() :
event.widget.tk_focusPrev().focus()
event.widget.tk_focusPrev().selection_range(0,tk.END)
elif event.widget.index(tk.INSERT)==0:
if event.widget.tk_focusPrev().winfo_parent()==event.widget.winfo_parent() :
if len(event.widget.get())>0:
event.widget.tk_focusPrev().focus()
event.widget.tk_focusPrev().selection_range(0,tk.END)
event.widget.selection_range(0,tk.END)
return("break")
def next(self,event):
event.widget.tk_focusNext().focus()
event.widget.tk_focusNext().selection_range(0,tk.END)
return("break")
def next1(self,event):
#print(event.widget.index(tk.END),len(str(event.widget.getMaxvalue())))
if event.widget.selection_present()==True:
if event.widget.tk_focusNext().winfo_parent()==event.widget.winfo_parent():
event.widget.tk_focusNext().focus()
event.widget.tk_focusNext().selection_range(0,tk.END)
else:
event.widget.tk_focusNext().focus()
return("break")
elif event.widget.index(tk.INSERT)==event.widget.index(tk.END):
if event.widget.tk_focusNext().winfo_parent()==event.widget.winfo_parent():
if len(event.widget.get())>0:
event.widget.tk_focusNext().focus()
event.widget.tk_focusNext().selection_range(0,tk.END)
#return("break")
else:
if len(event.widget.get())==4:
event.widget.tk_focusNext().focus()
event.widget.selection_range(0,tk.END)
return("break")
#return("break")
def stateDisable(self):
self.config(bg='lightgrey')
self.lbl1.config(bg='lightgrey')
self.lbl2.config(bg='lightgrey')
self.day_entry.config(disabledbackground='lightgrey')
self.month_entry.config(disabledbackground='lightgrey')
self.year_entry.config(disabledbackground='lightgrey')
self.day_entry.config(state='disable')
self.month_entry.config(state='disable')
self.year_entry.config(state='disable')
#def Bindnext(self):
def stateNormal(self):
self.config(bg='white')
self.lbl1.config(bg='white')
self.lbl2.config(bg='white')
self.day_entry.config(state='normal')
self.month_entry.config(state='normal')
self.year_entry.config(state='normal')
def stateReadOnly(self):
self.config(bg='lightgrey')
self.lbl1.config(bg='lightgrey')
self.lbl2.config(bg='lightgrey')
self.day_entry.config(disabledbackground='lightgrey')
self.month_entry.config(disabledbackground='lightgrey')
self.year_entry.config(disabledbackground='lightgrey')
self.day_entry.config(state='readonly')
self.month_entry.config(state='readonly')
self.year_entry.config(state='readonly')
def focus(self):
self.day_entry.focus()
def setDate(self,d):
#self._year_var.set(d.year)
#self._month_var.set('%d'% d.month)
#self._day_var.set('%d' %d.day)
print(d.year)
print(d.month)
print(d.day)
day=d.day
month=d.month
if len(str(d.day))==1:
day='0'+str(d.day)
if len(str(d.month))==1:
month='0'+str(d.month)
self.day_entry.setMaxvalue(31)
self.day_entry.delete(0,tk.END)
self.month_entry.delete(0,tk.END)
self.year_entry.delete(0,tk.END)
self.year_entry.insert(0,d.year)
#self._month_updated()
self.month_entry.insert(0,month)
self._month_updated()
self.day_entry.insert(0, day)
if isinstance(d, datetime.datetime):
self._time = d.time()
else:
self._time = None
def getDate(self):
try:
d = datetime.datetime(year=int(self.year_entry.get()),
month=int(self.month_entry.get()),
day=int(self.day_entry.get()))
if self._time:
d = d.replace(hour=self._time.hour,
minute=self._time.minute,
second=self._time.second)
return d
except:
if self.start_date==None:
self.setDate(datetime.date.today())
self.focus()
return self.getDate()
else:
self.setDate( self.start_date)
self.focus()
return self.getDate()
def dateEvent(self,event,function):
d = datetime.datetime(year=self._year_var.get(),
month=self._month_var.get(),
day=self._day_var.get())
if self._time:
d = d.replace(hour=self._time.hour,
minute=self._time.minute,
second=self._time.second)
self.year_entry.bind(event,function)
self.day_entry.bind(event,function)
self.month_entry.bind(event,function)
def _month_updated(self, event=None):
"""Update the day entry so that we have the correct end date for
the month
"""
if len(self.year_entry.get())>0 and len(self.month_entry.get())>0 and len(self.day_entry.get())>0:
self._update_day_values(int(self.year_entry.get()),
int(self.month_entry.get()),
int(self.day_entry.get()))
def _update_day_values(self, year, month, day):
"""Update the day entry with the correct values
"""
_, days_in_month = calendar.monthrange(year, month)
new_day = None
if day:
current_last_day =self.day_entry.getMaxvalue()#int(self.day_entry['values'][-1])
if current_last_day > days_in_month and day > days_in_month:
new_day = days_in_month
#self.day_entry.setMaxvalue(days_in_month)
if new_day:
self.day_entry.delete(0,tk.END)
self.day_entry.insert(0,new_day)
#self._day_var.set('%d' % new_day)
'''def _update_day_values(self, year, month, day):
"""Update the day combo box with the correct values
"""
_, days_in_month = calendar.monthrange(year, month)
new_day = None
if self.day_entry['values']:
current_last_day = int(self.day_entry['values'][-1])
if current_last_day > days_in_month and day > days_in_month:
new_day = days_in_month
self.day_entry['values'] = \
['%d' % (x + 1) for x in range(days_in_month)]
if new_day:
self._day_var.set('%d' % new_day)
def _month_updated(self, event=None):
"""Update the day combo box so that we have the correct end date for
the month
"""
self._update_day_values(self._year_var.get(),
self._month_var.get(),
self._day_var.get())'''
@property
def date(self):
"""The :class:`~datetime.date` represented by the entry."""
if self.day_entry is not None:
''''d = datetime.datetime(year=self._year_var.get(),
month=self._month_var.get(),
day=self._day_var.get())
if self._time:
d = d.replace(hour=self._time.hour,
minute=self._time.minute,
second=self._time.second)
print(self.day_entry.get(),'my value')'''
d=self.getDate()
return d
@date.setter
def date(self, d):
self.day_entry.setMaxvalue(31)
self._year_var.set(d.year)
self._month_var.set('%d'% d.month)
self._day_var.set('%d' %d.day)
print(d.year)
print(d.month)
print(d.day)
day=d.day
month=d.month
if len(str(d.day))==1:
day='0'+str(d.day)
if len(str(d.month))==1:
month='0'+str(d.month)
if self.day_entry is not None:
self.day_entry.delete(0,tk.END)
self.month_entry.delete(0,tk.END)
self.year_entry.delete(0,tk.END)
self.year_entry.insert(0,d.year)
#self._month_updated()
self.month_entry.insert(0,month)
self.day_entry.insert(0,day)
self._month_updated()
if isinstance(d, datetime.datetime):
self._time = d.time()
else:
self._time = None
def checkDate(self,event):
try:
if len(event.widget.get())==1 and event.widget.getMaxvalue()<50:
value='0'+str(event.widget.get())
event.widget.delete(0,tk.END)
event.widget.insert(0,value)
if event.widget.focus_get() is None or event.widget is None:
pass
else:
if event.widget.focus_get().winfo_parent()!=event.widget.winfo_parent():
import datetime
correctDate = None
try:
y=int(self.year_entry.get())
m=int(self.month_entry.get())
d=int(self.day_entry.get())
newDate = datetime.datetime(y,m,d)
correctDate = False
if newDate>=datetime.datetime(1950,1,1) and newDate<=datetime.datetime(2050,12,31):
correctDate=True
except:
correctDate = False
print(str(correctDate))
if correctDate==True:
pass
else:
if self.start_date==None:
self.setDate(datetime.date.today())
self.focus()
else:
self.setDate( self.start_date)
self.focus()
#return correctDate
else:
pass
except:
pass
def checkFocusNext(self,event):
if event.widget.index(tk.INSERT)==event.widget.index(tk.END) and event.widget.selection_present()==False:
if event.widget.tk_focusNext().winfo_parent()==event.widget.winfo_parent():
if len(event.widget.get())>0:
if event.widget.getMaxvalue()==12 and int(event.widget.get())>1 or len(event.widget.get())==2:
event.widget.tk_focusNext().focus()
elif event.widget.getMaxvalue()>12 and int(event.widget.get())>3 or len(event.widget.get())==2 :
event.widget.tk_focusNext().focus()
else:
if len(event.widget.get())>0:
if event.widget.getMaxvalue()>31 and int(event.widget.get())>1950 or len(event.widget.get())==4 :
event.widget.tk_focusNext().focus()
return("break")
'''if len(event.widget.get())==2 and event.widget.selection_present()==False:
event.widget.tk_focusNext().focus()
return False
#self.next(event)'''
def setStartDate(self,date):
self.start_date=date
def _select_date(self):
"""Display the date selection dialog"""
d = datetime.date(year=self._year_var.get(),
month=self._month_var.get(),
day=self._day_var.get())
dlg = DateDialog(self,
_('Select a Date...'),
start_date=d,
locale=self._locale,
font=self._font)
self.wait_window(dlg)
new_date = dlg.date
if new_date != None:
self.date = new_date
if __name__ == '__main__':
root = tk.Tk()
root.title('Date Test')
'''entry = tk.Entry(root)
#entry.config(state='readonly')
#entry.stateDisable()
entry.grid(row=0, column=0, sticky=tk.EW)
entry = tk.Entry(root)
#entry.config(state='readonly')
#entry.stateDisable()
entry.grid(row=0, column=1, sticky=tk.EW)'''
d=datetime.datetime.now()
cwd=d.strptime(str('2018/4/1'),"%Y/%m/%d")
entry = DateEntry(root,start_date=cwd, locale='pt')
#entry.config(state='readonly')
#entry.stateDisable()
entry.grid(row=0, column=0, sticky=tk.EW)
#entry.setDate(datetime.date.today())
'''entry = tk.Entry(root)
#entry.config(state='readonly')
#entry.stateDisable()
entry.grid(row=0, column=3, sticky=tk.EW)
entry = tk.Entry(root)
#entry.config(state='readonly')
#entry.stateDisable()
entry.grid(row=0, column=4, sticky=tk.EW)'''
def show_date():
#pass
print(entry.getDate())
#print(entry.getDate().strftime("%d/%m/%y"))
tk.Button(root,command=show_date).grid(row=1,column=0)
#entry.date='2018-1-1'
#entry.dateEvent('<FocusOut>',abc)
d=datetime.datetime.now()
cwd=d.strptime(str('2018/1/1'),"%Y/%m/%d")
print(cwd)
entry.date=cwd
entry.focus()
root.columnconfigure(0, weight=1)
show_date()
root.mainloop()