¿Cómo creo un selector de fecha en tkinter?

¿Hay alguna forma estándar de que las aplicaciones tkinter permitan al usuario elegir una fecha?

No, Tk no incluye un widget de selector de fecha. Hay un par de widgets de calendario de Python que podrías probar:

http://svn.python.org/projects/sandbox/trunk/ttk-gsoc/samples/ttkcalendar.py

http://effbot.org/zone/wcklib-calendar.htm

No tan lejos como pude encontrar. Para quien quiera hacer esto en el futuro:

Usé tkSimpleDialog y ttkcalendar.py (con modificaciones de esta publicación SO) para hacer un CalendarDialog . Las versiones modificadas de los tres archivos están disponibles en mi github .

A continuación se muestra el código en mi CalendarDialog.py :

import Tkinter import ttkcalendar import tkSimpleDialog class CalendarDialog(tkSimpleDialog.Dialog): """Dialog box that displays a calendar and returns the selected date""" def body(self, master): self.calendar = ttkcalendar.Calendar(master) self.calendar.pack() def apply(self): self.result = self.calendar.selection # Demo code: def main(): root = Tkinter.Tk() root.wm_title("CalendarDialog Demo") def onclick(): cd = CalendarDialog(root) print cd.result button = Tkinter.Button(root, text="Click me to see a calendar!", command=onclick) button.pack() root.update() root.mainloop() if __name__ == "__main__": main() 

En caso de que alguien aún lo necesite, aquí hay un código simple para crear un widget de Calendar y DateEntry con el paquete tkcalendar.

pip install tkcalendar [para instalar el paquete]

 try: import tkinter as tk from tkinter import ttk except ImportError: import Tkinter as tk import ttk from tkcalendar import Calendar, DateEntry def example1(): def print_sel(): print(cal.selection_get()) top = tk.Toplevel(root) cal = Calendar(top, font="Arial 14", selectmode='day', cursor="hand1", year=2018, month=2, day=5) cal.pack(fill="both", expand=True) ttk.Button(top, text="ok", command=print_sel).pack() def example2(): top = tk.Toplevel(root) ttk.Label(top, text='Choose date').pack(padx=10, pady=10) cal = DateEntry(top, width=12, background='darkblue', foreground='white', borderwidth=2) cal.pack(padx=10, pady=10) root = tk.Tk() s = ttk.Style(root) s.theme_use('clam') ttk.Button(root, text='Calendar', command=example1).pack(padx=10, pady=10) ttk.Button(root, text='DateEntry', command=example2).pack(padx=10, pady=10) root.mainloop() 

No, pero puede obtenerlo del usuario como un elemento de fecha y hora de una cadena con formato.

Ejemplo:

 import datetime userdatestring = '2013-05-10' thedate = datetime.datetime.strptime(userdatestring, '%Y-%m-%d') 

Consulte http://docs.python.org/2/library/datetime.html#strftime-strptime-behavior . Es práctico, aunque no es la forma más fácil de conseguir una cita.

Así es como codificamos un selector de fecha de python en tkinter.

 # !/usr/bin/env python # -*- coding: utf-8 -*- # Author: Rambarun Komaljeet # License: Freeware # --------------------------------------------------------------------------- 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, widget=None, format_str=None): """ :param widget: widget of parent instance. :param format_str: print format in which to display date. :type format_str: string Example:: a = MyDatePicker(self, widget=self.parent widget, format_str='%02d-%s-%s') """ super().__init__() self.widget = widget self.str_format = format_str self.title("Date Picker") self.resizable(0, 0) self.geometry("+630+390") 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 = 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 = self.month_names.index(self.month_str_var.get()) try: self.month_str_var.set(self.month_names[index_current_month + 1]) except IndexError: # index 13 does not exist, use index 1 instead, which is January. 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 dates 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): """ Description: Build a date button. :param date: date. :type date: string :param row: row number. :type row: string :param column: column number. :type column: string """ 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(\"\", self.get_date)" ) def delete_buttons(self, date): """ Description: Delete a date button. :param date: date. :type: string """ exec( "self.btn_" + str(date) + ".destroy()" ) def get_date(self, clicked=None): """ Description: Get the date from the calendar on button click. :param clicked: button clicked event. :type clicked: tkinter event """ clicked_button = clicked.widget year = self.year_str_var.get() month = self.month_str_var.get() date = clicked_button['text'] self.full_date = self.str_format % (date, month, year) print(self.full_date) # Replace with parent 'widget' of your choice. try: self.widget.delete(0, tk.END) self.widget.insert(0, self.full_date) except AttributeError: pass if __name__ == '__main__': def application(): MyDatePicker(format_str='%02d-%s-%s') root = tk.Tk() btn = tk.Button(root, text="test", command=application) btn.pack() root.mainloop()