[SOLVED] The following is a description of the accepted answer and source code for working with kivy DatePicker widgets.
I study Kivy and decided to make widgets for choosing a date as a training exercise.
import kivy kivy.require('1.4.0') from kivy.uix.gridlayout import GridLayout from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.uix.button import Button from kivy.app import App from datetime import date, timedelta class DatePicker(BoxLayout): def __init__(self, **kwargs): super(DatePicker, self).__init__(**kwargs) self.date = date.today() self.orientation = "vertical" self.header = BoxLayout(orientation = 'horizontal', size_hint = (1, 0.2)) self.body = GridLayout(cols = 7) self.add_widget(self.header) self.add_widget(self.body) self.populate_body() self.populate_header() def populate_header(self): self.header.clear_widgets() self.previous_month = Button(text = "<") self.next_month = Button(text = ">") self.current_month = Label(text = repr(self.date), size_hint = (2, 1)) self.header.add_widget(self.previous_month) self.header.add_widget(self.current_month) self.header.add_widget(self.next_month) def populate_body(self): self.body.clear_widgets() date_cursor = date(self.date.year, self.date.month, 1) while date_cursor.month == self.date.month: self.date_label = Label(text = str(date_cursor.day)) self.body.add_widget(self.date_label) date_cursor += timedelta(days = 1)
I hit the road block and cannot decide how to proceed. I want to add a method so that when I click on the date_labels, they set self.date for the date object with this part of the day.
I tried adding
self.date_label.bind(on_touch_down = self.set_date(date_cursor.day))
but just got maximum recursion errors.
DECISION:
import kivy kivy.require('1.4.0') from kivy.uix.gridlayout import GridLayout from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.uix.button import Button from kivy.app import App from datetime import date, timedelta from functools import partial class DatePicker(BoxLayout): def __init__(self, *args, **kwargs): super(DatePicker, self).__init__(**kwargs) self.date = date.today() self.orientation = "vertical" self.month_names = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') if kwargs.has_key("month_names"): self.month_names = kwargs['month_names'] self.header = BoxLayout(orientation = 'horizontal', size_hint = (1, 0.2)) self.body = GridLayout(cols = 7) self.add_widget(self.header) self.add_widget(self.body) self.populate_body() self.populate_header() def populate_header(self, *args, **kwargs): self.header.clear_widgets() previous_month = Button(text = "<") previous_month.bind(on_press=partial(self.move_previous_month)) next_month = Button(text = ">", on_press = self.move_next_month) next_month.bind(on_press=partial(self.move_next_month)) month_year_text = self.month_names[self.date.month -1] + ' ' + str(self.date.year) current_month = Label(text=month_year_text, size_hint = (2, 1)) self.header.add_widget(previous_month) self.header.add_widget(current_month) self.header.add_widget(next_month) def populate_body(self, *args, **kwargs): self.body.clear_widgets() date_cursor = date(self.date.year, self.date.month, 1) for filler in range(date_cursor.isoweekday()-1): self.body.add_widget(Label(text="")) while date_cursor.month == self.date.month: date_label = Button(text = str(date_cursor.day)) date_label.bind(on_press=partial(self.set_date, day=date_cursor.day)) if self.date.day == date_cursor.day: date_label.background_normal, date_label.background_down = date_label.background_down, date_label.background_normal self.body.add_widget(date_label) date_cursor += timedelta(days = 1) def set_date(self, *args, **kwargs): self.date = date(self.date.year, self.date.month, kwargs['day']) self.populate_body() self.populate_header() def move_next_month(self, *args, **kwargs): if self.date.month == 12: self.date = date(self.date.year + 1, 1, self.date.day) else: self.date = date(self.date.year, self.date.month + 1, self.date.day) self.populate_header() self.populate_body() def move_previous_month(self, *args, **kwargs): if self.date.month == 1: self.date = date(self.date.year - 1, 12, self.date.day) else: self.date = date(self.date.year, self.date.month -1, self.date.day) self.populate_header() self.populate_body() class MyApp(App): def build(self): return DatePicker() if __name__ == '__main__': MyApp().run()