2010-12-14 2 views
22

Есть ли какой-либо стандартный способ приложения tkinter, позволяющий пользователю выбирать дату?Как создать сборщик дат в tkinter?

+0

Непроизносимый, поскольку tkinter очень минималистичен. Если вы хотите что-то фантастическое, не строя его самостоятельно, ваш лучший выбор - один из самых больших наборов инструментов GUI с батарейками (я рекомендую Qt). – delnan

+9

+1 полностью разумный вопрос. Это тот тип пользовательского интерфейса, который должен быть стандартизован в наборе инструментов. Удивленный tk этого не предлагает. – Anne

ответ

14

Нет, Tk не включает виджет выбора даты. Есть несколько Python календарь виджетов вы можете попробовать:

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

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

+0

Спасибо, я посмотрю. Мой вопрос был - так как у них нет виджета - что сделали большинство разработчиков tk/tkinter? Просто есть три спин-бокса? Как насчет разных месяцев? Как насчет високосных лет? – MKaras

+2

, выступая в качестве разработчика ex-tcl/tk, я просто катал свои собственные несколько раз, когда мне это нужно. Они довольно тривиальны для создания, поскольку tcl (и python) имеют подпрограммы даты, которые могут подавать вам данные. Все, что вам нужно сделать, это создать сетку кнопок или что-то подобное. –

+1

Yup, здесь же; Tcl/Tk (и Tkinter) делают очень тривиальным создание новых виджетов. Если вы хотите, чтобы какая-то структура проверила комплект конструктора виджета (используемый календарем WCK, связанный выше). –

4

Нет, но вы можете получить его от пользователя в виде даты и времени элемента из отформатированной строки ..

Пример:

import datetime 

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

Отъезд http://docs.python.org/2/library/datetime.html#strftime-strptime-behavior. Это удобно, хотя и не самый удобный способ получить дату.

5

Не так далеко, как я мог найти. Для тех, кто хочет сделать это в будущем:

tkSimpleDialog Я использовал и ttkcalendar.py (с изменениями от this SO пост), чтобы сделать CalendarDialog. Эти три файла доступны на моем github.

Ниже приведен код в моем 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() 
+2

Хех, исходный файл python, который вы связали, на самом деле НЕ ИМЕЕТ этих модификаций, - столкнулся с камнем преткновения, пока я не понял, что его нужно модифицировать, чтобы заставить его играть с реальным приложением Tkinter: P –

+0

Да, вот почему Я связался с исправленными версиями на моем github. – Moshe

+0

Ahh gotcha, спасибо. Я просто предположил, что все ссылки отправились в одно и то же место, потому что я не читал их достаточно близко, чтобы увидеть, что они не все github: P –

0

Это, как мы код питона DatePicker в 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(\"<Button-1>\", 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() 
Смежные вопросы