[ĐÃ GIẢI PHÁP] Vui lòng xem bên dưới để áp dụng câu trả lời và mã nguồn được chấp nhận để hoạt động tiện ích DatePicker kivy.Tiện ích chọn ngày Kivy
Tôi đã học Kivy và quyết định đặt tiện ích con chọn ngày làm bài tập học tập.
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()
Tôi đã nhấn một khối đường và không thể biết cách tiếp tục. Tôi muốn thêm một phương thức sao cho khi các date_labels được bấm, chúng đặt self.date thành một đối tượng ngày với phần ngày đó.
Tôi đã thử thêm
self.date_label.bind(on_touch_down = self.set_date(date_cursor.day))
nhưng chỉ có lỗi đệ quy tối đa.
SOLUTION:
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()
Ngoài ra, dưới dạng nhận xét vì nó không phải là câu hỏi của bạn, nhưng bạn không cần lưu trữ trong trường hợp của bạn nếu bạn không sử dụng giá trị sau, vì vậy trong populate_body, 'self.date_label' có thể được thay thế bằng chỉ' date_label' ở mọi nơi. Lưu ý phụ, xin hãy tôn trọng pep8: P, không có khoảng trống xung quanh '=' trong một cuộc gọi fonction, hai, và chỉ có hai dòng giữa mỗi định nghĩa lớp. có một ngày tốt đẹp :) chỉnh sửa: oh cũng cảm ơn vì đã chọn ngày cho kivy, tôi chắc chắn rằng nó có thể hữu ích cho người khác :) – Tshirtman
Vâng, tôi đã trải qua một số lần lặp lại date_label và self.date_label và chỉ xảy ra để đăng trong biểu mẫu này. Tôi thấy hình đại diện của bạn ở khắp mọi nơi bằng cách này, bất cứ khi nào tôi tìm kiếm nội dung. Tôi đã bắt đầu nghĩ rằng đó là một loại avatar mặc định/meme! – Horba
Hehe, tốt, tôi cố gắng trả lời tất cả các câu hỏi kivy ^^ – Tshirtman