How do I create a date picker in tkinter?

前端 未结 7 1393
借酒劲吻你
借酒劲吻你 2020-11-28 09:45

Is there any standard way tkinter apps allow the user to choose a date?

7条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-28 10:13

    This is how we code a python datepicker in 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()
    

提交回复
热议问题