无法更改 KivyMD 中的 InputBox 内容
Can't change an InputBox content in KivyMD
我正在尝试制作一个启动日期选择器的 InputBox,当您 select 一个日期时,它将出现在框中。所以我这样打结:
from kivymd.app import MDApp
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.menu import MDDropdownMenu
from kivy.metrics import dp
from kivymd.uix.snackbar import Snackbar
from kivymd.uix.dialog import MDDialog
from kivymd.uix.picker import MDDatePicker
class MainScreen(Screen):
pass
class Predef(Screen):
pass
class WindowManager(ScreenManager):
pass
class MyApp(MDApp):
def build(self):
self.birthday = ''
kv = Builder.load_file('file.kv')
return kv
def on_save(self, instance, value, date_range):
print(value)
self.birthday = value
self.root.ids.input_box_date.text = self.birthday
def on_cancel(self, instance, value):
print("cancel")
def date(self):
date_dialog = MDDatePicker(
title='Birthday',
title_input= 'Birthday'
)
date_dialog.bind(on_save=self.on_save, on_cancel=self.on_cancel)
date_dialog.open()
if __name__ == '__main__':
MyApp().run()
这是 kv 文件中的代码:
WindowManager:
MainScreen:
Predef:
<MainScreen>:
name: "main"
MDBoxLayout:
orientation: 'vertical'
size: root.width, root.height
MDToolbar:
title: "App"
left_action_items: [["menu", lambda x: side_bar.set_state("open")]]
Label:
text: 'Image'
color: (0, 0, 0, 1)
MDBottomAppBar:
MDToolbar:
icon: "botão.png"
type: "bottom"
MDNavigationDrawer:
id: side_bar
BoxLayout:
orientation: 'vertical'
padding: '16dp'
Label:
color: (0, 0, 0, 1)
font_size: 35
text: 'Settings '
size_hint_y: None
height: self.texture_size[1]
pos_hint: {'y': 0, 'left': 1}
ScrollView:
MDList:
OneLineListItem:
text: 'Predefitions'
on_release:
side_bar.set_state("close")
app.root.current = 'Predef'
root.manager.transition.direction = "up"
<Predef>:
name: 'Predef'
MDBoxLayout:
orientation: 'vertical'
size: root.height, root.width
MDToolbar:
title: "Predefinitions"
left_action_items: [["menu", lambda x: bar.set_state("open")]]
pos_hint: {'x': 0, 'top': 1}
Label:
color: (0, 0, 0, 1)
text: 'Birthday'
MDTextFieldRound:
id: input_box_date
hint_text: "Birthday"
text: app.birthday
size_hint_x : 0.5
pos_hint: {'center_x' : 0.5}
on_focus: app.date()
Label:
text: ''
MDNavigationDrawer:
id: bar
BoxLayout:
orientation: 'vertical'
padding: '16dp'
Label:
color: (0, 0, 0, 1)
font_size: 35
text: 'Settings '
size_hint_y: None
height: self.texture_size[1]
pos_hint: {'y': 0, 'left': 1}
ScrollView:
MDList:
OneLineListItem:
text: 'Main Screen'
on_release:
bar.set_state("close")
app.root.current = 'main'
root.manager.transition.direction = "up"
启动时一切正常。 InputBox 如我所料开始为空,但是当我单击“确定”按钮时出现此错误:
'''
[INFO ] [Base ] Leaving application in progress...
Traceback (most recent call last):
File "kivy\properties.pyx", line 861, in kivy.properties.ObservableDict.__getattr__
KeyError: 'input_box_date'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\program.py", line 112, in <module>
MyApp().run()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\app.py", line 950, in run
runTouchApp()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 582, in runTouchApp
EventLoop.mainloop()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 347, in mainloop
self.idle()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 391, in idle
self.dispatch_input()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 342, in dispatch_input
post_dispatch_input(*pop(0))
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 308, in post_dispatch_input
wid.dispatch('on_touch_up', me)
File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivymd\uix\behaviors\ripple_behavior.py", line 296, in on_touch_up
return super().on_touch_up(touch)
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivymd\uix\button.py", line 981, in on_touch_up
return super().on_touch_up(touch)
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
self.dispatch('on_release')
File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1132, in kivy._event.EventObservers._dispatch
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 57, in custom_callback
exec(__kvlang__.co_value, idmap)
File "<string>", line 213, in <module>
File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1172, in kivy._event.EventObservers._dispatch
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\program.py", line 77, in on_save
self.root.ids.input_box_date.text = self.birthday
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
'''
我不知道为什么会出现此错误。我尝试用 self.root.ids.input_box_date.text = "string"
替换 self.root.ids.input_box_date.text = self.birthday
,但没有任何变化。我该怎么办?
错误消息显示 KeyError: 'input_box_date'
。这意味着您使用的 ids
中没有 input_box_date
键。该键在 <Predef>:
规则中定义,因此 id
将在 Predef
实例的 ids
中。解决方法是使用 Predef
实例访问 id
。尝试替换:
self.root.ids.input_box_date.text = self.birthday
与:
self.root.get_screen('Predef').ids.input_box_date.text = self.birthday
TL;DR: 屏幕在 root 和 ids 和 date-picker returns datetime.date
需要转换为 string for text-field: self.root.get_screen('Predef').ids.input_box_datex.text = str(value)
.
根和child仁
在您的 KV 文件中,您在 root WindowManager
:
中定义了两个屏幕
WindowManager:
MainScreen:
Predef:
在您的 python 脚本中使用 self.root
访问此 root。
所以 print(self.root)
将给出类似的输出:
<main.WindowManager object at 0x7fa580c48f28>
在此根目录中,screens
可以使用 self.root.screens
作为索引列表找到。打印将输出:
[<Screen name='main'>, <Screen name='Predef'>]
按索引访问屏幕,例如第一次使用 screens[0]
或给定 id 的特定屏幕使用 get_screen(id)
.
屏幕上的所有 Kivy 小部件都具有 children
:
所有这些 child 小部件都有 ids,可以使用 self.root.get_screen('Predef').ids
将其列为字典:
{'input_box_date': <WeakProxy to <kivymd.uix.textfield.MDTextFieldRound object at 0x7fc1aa8c9c88>>, 'bar': <WeakProxy to <kivymd.uix.navigationdrawer.MDNavigationDrawer object at 0x7fc1a9c9dc88>>}
并由 ids['input_box_date']
或 ids.input_box_date
访问。
另请参阅:
设置日期 text-field
因为 text-field 是在 screen 内部定义的,id 为 'Predef'
,所以使用其中一个:
self.root.get_screen('Predef').ids['input_box_date']
self.root.get_screen('Predef').ids.input_box_date
但是 date-picker returns 类型的值 datetime
因此您需要使用 str()
:
将其转换为字符串
def on_save(self, instance, value, date_range):
print("value/type:", value, type(value))
self.birthday = value # the instance variable becomes of type date
self.root.get_screen('Predef').ids.input_box_date.text = str(date) # convert to string
另请参阅:
访问树中的相关元素
print(self.root)
print(self.root.screens)
print(self.root.screens[1].ids)
print(self.root.screens[1].ids.input_box_date)
print(self.root.get_screen('Predef').children)
print(self.root.get_screen('Predef').ids['input_box_date'])
print(self.root.get_screen('Predef').ids.input_box_date)
参见:
我正在尝试制作一个启动日期选择器的 InputBox,当您 select 一个日期时,它将出现在框中。所以我这样打结:
from kivymd.app import MDApp
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.menu import MDDropdownMenu
from kivy.metrics import dp
from kivymd.uix.snackbar import Snackbar
from kivymd.uix.dialog import MDDialog
from kivymd.uix.picker import MDDatePicker
class MainScreen(Screen):
pass
class Predef(Screen):
pass
class WindowManager(ScreenManager):
pass
class MyApp(MDApp):
def build(self):
self.birthday = ''
kv = Builder.load_file('file.kv')
return kv
def on_save(self, instance, value, date_range):
print(value)
self.birthday = value
self.root.ids.input_box_date.text = self.birthday
def on_cancel(self, instance, value):
print("cancel")
def date(self):
date_dialog = MDDatePicker(
title='Birthday',
title_input= 'Birthday'
)
date_dialog.bind(on_save=self.on_save, on_cancel=self.on_cancel)
date_dialog.open()
if __name__ == '__main__':
MyApp().run()
这是 kv 文件中的代码:
WindowManager:
MainScreen:
Predef:
<MainScreen>:
name: "main"
MDBoxLayout:
orientation: 'vertical'
size: root.width, root.height
MDToolbar:
title: "App"
left_action_items: [["menu", lambda x: side_bar.set_state("open")]]
Label:
text: 'Image'
color: (0, 0, 0, 1)
MDBottomAppBar:
MDToolbar:
icon: "botão.png"
type: "bottom"
MDNavigationDrawer:
id: side_bar
BoxLayout:
orientation: 'vertical'
padding: '16dp'
Label:
color: (0, 0, 0, 1)
font_size: 35
text: 'Settings '
size_hint_y: None
height: self.texture_size[1]
pos_hint: {'y': 0, 'left': 1}
ScrollView:
MDList:
OneLineListItem:
text: 'Predefitions'
on_release:
side_bar.set_state("close")
app.root.current = 'Predef'
root.manager.transition.direction = "up"
<Predef>:
name: 'Predef'
MDBoxLayout:
orientation: 'vertical'
size: root.height, root.width
MDToolbar:
title: "Predefinitions"
left_action_items: [["menu", lambda x: bar.set_state("open")]]
pos_hint: {'x': 0, 'top': 1}
Label:
color: (0, 0, 0, 1)
text: 'Birthday'
MDTextFieldRound:
id: input_box_date
hint_text: "Birthday"
text: app.birthday
size_hint_x : 0.5
pos_hint: {'center_x' : 0.5}
on_focus: app.date()
Label:
text: ''
MDNavigationDrawer:
id: bar
BoxLayout:
orientation: 'vertical'
padding: '16dp'
Label:
color: (0, 0, 0, 1)
font_size: 35
text: 'Settings '
size_hint_y: None
height: self.texture_size[1]
pos_hint: {'y': 0, 'left': 1}
ScrollView:
MDList:
OneLineListItem:
text: 'Main Screen'
on_release:
bar.set_state("close")
app.root.current = 'main'
root.manager.transition.direction = "up"
启动时一切正常。 InputBox 如我所料开始为空,但是当我单击“确定”按钮时出现此错误:
'''
[INFO ] [Base ] Leaving application in progress...
Traceback (most recent call last):
File "kivy\properties.pyx", line 861, in kivy.properties.ObservableDict.__getattr__
KeyError: 'input_box_date'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\program.py", line 112, in <module>
MyApp().run()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\app.py", line 950, in run
runTouchApp()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 582, in runTouchApp
EventLoop.mainloop()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 347, in mainloop
self.idle()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 391, in idle
self.dispatch_input()
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 342, in dispatch_input
post_dispatch_input(*pop(0))
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 308, in post_dispatch_input
wid.dispatch('on_touch_up', me)
File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivymd\uix\behaviors\ripple_behavior.py", line 296, in on_touch_up
return super().on_touch_up(touch)
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivymd\uix\button.py", line 981, in on_touch_up
return super().on_touch_up(touch)
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
self.dispatch('on_release')
File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1132, in kivy._event.EventObservers._dispatch
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 57, in custom_callback
exec(__kvlang__.co_value, idmap)
File "<string>", line 213, in <module>
File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1172, in kivy._event.EventObservers._dispatch
File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\program.py", line 77, in on_save
self.root.ids.input_box_date.text = self.birthday
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
'''
我不知道为什么会出现此错误。我尝试用 self.root.ids.input_box_date.text = "string"
替换 self.root.ids.input_box_date.text = self.birthday
,但没有任何变化。我该怎么办?
错误消息显示 KeyError: 'input_box_date'
。这意味着您使用的 ids
中没有 input_box_date
键。该键在 <Predef>:
规则中定义,因此 id
将在 Predef
实例的 ids
中。解决方法是使用 Predef
实例访问 id
。尝试替换:
self.root.ids.input_box_date.text = self.birthday
与:
self.root.get_screen('Predef').ids.input_box_date.text = self.birthday
TL;DR: 屏幕在 root 和 ids 和 date-picker returns datetime.date
需要转换为 string for text-field: self.root.get_screen('Predef').ids.input_box_datex.text = str(value)
.
根和child仁
在您的 KV 文件中,您在 root WindowManager
:
WindowManager:
MainScreen:
Predef:
在您的 python 脚本中使用 self.root
访问此 root。
所以 print(self.root)
将给出类似的输出:
<main.WindowManager object at 0x7fa580c48f28>
在此根目录中,screens
可以使用 self.root.screens
作为索引列表找到。打印将输出:
[<Screen name='main'>, <Screen name='Predef'>]
按索引访问屏幕,例如第一次使用 screens[0]
或给定 id 的特定屏幕使用 get_screen(id)
.
屏幕上的所有 Kivy 小部件都具有 children
:
所有这些 child 小部件都有 ids,可以使用 self.root.get_screen('Predef').ids
将其列为字典:
{'input_box_date': <WeakProxy to <kivymd.uix.textfield.MDTextFieldRound object at 0x7fc1aa8c9c88>>, 'bar': <WeakProxy to <kivymd.uix.navigationdrawer.MDNavigationDrawer object at 0x7fc1a9c9dc88>>}
并由 ids['input_box_date']
或 ids.input_box_date
访问。
另请参阅:
设置日期 text-field
因为 text-field 是在 screen 内部定义的,id 为 'Predef'
,所以使用其中一个:
self.root.get_screen('Predef').ids['input_box_date']
self.root.get_screen('Predef').ids.input_box_date
但是 date-picker returns 类型的值 datetime
因此您需要使用 str()
:
def on_save(self, instance, value, date_range):
print("value/type:", value, type(value))
self.birthday = value # the instance variable becomes of type date
self.root.get_screen('Predef').ids.input_box_date.text = str(date) # convert to string
另请参阅:
访问树中的相关元素
print(self.root)
print(self.root.screens)
print(self.root.screens[1].ids)
print(self.root.screens[1].ids.input_box_date)
print(self.root.get_screen('Predef').children)
print(self.root.get_screen('Predef').ids['input_box_date'])
print(self.root.get_screen('Predef').ids.input_box_date)
参见: