2012-12-04 12 views
6

[सोल्वड] कृपया काम करने वाले किवी डेटपिकर विजेट के लिए स्वीकृत उत्तर और स्रोत कोड के आवेदन के लिए नीचे देखें।किवी डेट पिकर विजेट

मैं किवी सीख रहा हूं और एक सीखने के अभ्यास के रूप में एक तारीख पिकर विजेट बनाने का फैसला किया है।

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) 

# Not yet implimented ### 
# def set_date(self, day): 
#  self.date = date(self.date.year, self.date.month, day) 
#  self.populate_body() 
#  self.populate_header() 
# 
# def move_next_month(self): 
#  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) 
# def move_previous_month(self): 
#  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() 

मैं एक सड़क ब्लॉक पर पहुंच जाते हैं और बाहर काम नहीं कर सकता जारी रखने के लिए कैसे। मैं एक विधि जोड़ना चाहता हूं कि जब date_labels पर क्लिक किया जाता है, तो उन्होंने उस दिन भाग के साथ एक डेट ऑब्जेक्ट में self.date सेट किया है।

मैं

self.date_label.bind(on_touch_down = self.set_date(date_cursor.day)) 

जोड़ने की कोशिश की है, लेकिन केवल अधिकतम प्रत्यावर्तन त्रुटियों मिला है।

समाधान:

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() 
+1

इसके अलावा, एक टिप्पणी के रूप में, क्योंकि यह आपका प्रश्न नहीं है, लेकिन अगर आप मूल्य का उपयोग नहीं करेंगे, तो आप अपने उदाहरण में स्टोर करने की आवश्यकता नहीं है, इसलिए populate_body में, 'self.date_label' को' date_label' कहीं भी। साइड नोट पर एक साइड नोट के रूप में, कृपया पेप 8 का सम्मान करें: पी, फॉक्शन कॉल में '= 'के आसपास कोई रिक्त स्थान नहीं, और प्रत्येक वर्ग परिभाषा के बीच केवल दो पंक्तियां। एक अच्छा दिन है :) संपादित करें: ओह भी kivy के लिए एक तारीख पिकर बनाने के लिए धन्यवाद, मुझे यकीन है कि यह दूसरों के लिए उपयोगी हो सकता है :) – Tshirtman

+0

हाँ, मैं date_label और self.date_label के कई पुनरावृत्तियों के माध्यम से चला गया और बस पोस्ट के साथ हुआ इस रूप में जब भी मैं सामान देख रहा हूं, मैं हर जगह अपना अवतार देखता हूं। मुझे लगता है कि यह किसी प्रकार का डिफ़ॉल्ट/मेम अवतार था! – Horba

+0

हे, ठीक है, मैं सभी किवी सवालों के जवाब देने का प्रयास करता हूं ^^ – Tshirtman

उत्तर

3

आप अपने बंधन में एक छोटी सी गलती करते हैं, आप कॉल विधि के बजाय गुजर यह (इस प्रकार, आप self.set_date(date_cursor.day) का परिणाम गुजरती हैं, लेकिन बुला self.set_date कॉल self.populate_body भी , तो आप एक अनंत रिकर्सन में आते हैं, केवल पाइथन रिकर्सन सीमा से ही रोका जाता है।

आप जो करना चाहते हैं वह विधि को बांधना है लेकिन date_cursor.day के साथ पहले पैरामीटर के रूप में, सेफ़ंक्शन सही है।

self.date_label.bind(on_touch_down=partial(self.set_date, date_cursor.day))

एक नया fonction बनाता है, कि सिर्फ self.set_date तरह है, लेकिन date_cursor.day पहली बार एक तर्क के रूप में पहले से लोड के साथ।

संपादित करें: भी, जब आपके आंशिक समारोह घटना जुड़ कर कहा जाता है, यह अन्य तर्कों प्राप्त होगा, तो यह यहाँ set_date कार्य/तरीकों में अपने तर्क के अंत में **args जोड़ने के लिए एक अच्छी आदत है आप गधा कॉलबैक का उपयोग करें ()।

+0

धन्यवाद, मुझे पता था कि यह ऐसा कुछ होगा लेकिन फ़ंक्शन को कॉल किए बिना आवश्यक तर्कों में गुजरने के लिए मेरा सिर नहीं मिल सका। functools यह है! मैं आज रात इस पर काम करने जा रहा हूं और वापस रिपोर्ट करूंगा। – Horba

संबंधित मुद्दे