如何使用 on_enter 函数在第一屏更新 KivyMD 标签?
How to Update KivyMD Label in the first screen with on_enter function?
下面给出的是来自https://github.com/attreyabhatt/KivyMD-Basics/blob/master/13%20-%20Switching%20Screens/main.py
的kivyMD屏幕管理器程序
我已经把它添加到KivyMD的官方导航抽屉程序https://kivymd.readthedocs.io/en/latest/components/navigation-drawer/index.html中
该程序运行良好,但我想使用 on_enter 函数更改 MenuScreen 中的文本。
我在class MenuScreen
里面评论了def on_enter
。
如果我们 运行 它取消注释显示此错误:
Traceback (most recent call last):
File "kivy\properties.pyx", line 861, in kivy.properties.ObservableDict.__getattr__
KeyError: 'label_id'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/kivy_prj1/kivy_mainmd/nav_screen.py", line 170, in <module>
sm.add_widget(MenuScreen(name='menu'))
File "C:\Users\Administrator\pyenv\lt_kivyvirt\lib\site-packages\kivy\uix\screenmanager.py", line 997, in add_widget
self.current = screen.name
File "kivy\properties.pyx", line 498, in kivy.properties.Property.__set__
File "kivy\properties.pyx", line 545, in kivy.properties.Property.set
File "kivy\properties.pyx", line 600, in kivy.properties.Property.dispatch
File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1154, in kivy._event.EventObservers._dispatch
File "C:\Users\Administrator\pyenv\lt_kivyvirt\lib\site-packages\kivy\uix\screenmanager.py", line 1062, in on_current
screen.dispatch('on_enter')
File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
File "C:/Users/Administrator/PycharmProjects/kivy_prj1/kivy_mainmd/nav_screen.py", line 156, in on_enter
self.ids.label_id.text = "Label text Updated"
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
'label_id'是我要改标签的id。
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty, ListProperty
from kivymd.app import MDApp
from kivymd.theming import ThemableBehavior
from kivymd.uix.list import OneLineIconListItem, MDList
from kivy.uix.screenmanager import ScreenManager, Screen
KV = '''
# Menu item in the DrawerList list.
<ItemDrawer>:
theme_text_color: "Custom"
on_release: self.parent.set_color_item(self)
IconLeftWidget:
id: icon
icon: root.icon
theme_text_color: "Custom"
text_color: root.text_color
<ContentNavigationDrawer>:
orientation: "vertical"
padding: "8dp"
spacing: "8dp"
AnchorLayout:
anchor_x: "left"
size_hint_y: None
height: avatar.height
Image:
id: avatar
size_hint: None, None
size: "56dp", "56dp"
source: "data/logo/kivy-icon-256.png"
MDLabel:
text: "KivyMD library"
font_style: "Button"
size_hint_y: None
height: self.texture_size[1]
MDLabel:
text: "kivydevelopment@gmail.com"
font_style: "Caption"
size_hint_y: None
height: self.texture_size[1]
ScrollView:
DrawerList:
id: md_list
Screen:
ScreenManager:
MenuScreen:
ProfileScreen:
UploadScreen:
NavigationLayout:
ScreenManager:
Screen:
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: "Navigation Drawer"
elevation: 10
left_action_items: [['menu', lambda x: nav_drawer.toggle_nav_drawer()]]
Widget:
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
id: content_drawer
<MenuScreen>:
name: 'menu'
MDRectangleFlatButton:
text: 'Profile'
pos_hint: {'center_x':0.5,'center_y':0.6}
on_press: root.manager.current = 'profile'
MDRectangleFlatButton:
text: 'Upload'
pos_hint: {'center_x':0.5,'center_y':0.5}
on_press: root.manager.current = 'upload'
MDLabel:
id:label_id
text: 'update this at on enter'
pos_hint: {'center_x':0.5,'center_y':0.4}
halign: 'center'
<ProfileScreen>:
name: 'profile'
MDLabel:
text: 'Profile'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.1}
on_press: root.manager.current = 'menu'
<UploadScreen>:
name: 'upload'
MDLabel:
text: 'Upload'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.1}
on_press: root.manager.current = 'menu'
'''
class ContentNavigationDrawer(BoxLayout):
pass
class ItemDrawer(OneLineIconListItem):
icon = StringProperty()
text_color = ListProperty((0, 0, 0, 1))
"""Instead of just giving MDList in kv file give DrawerList for adding the ThemableBehavior with it and created color
changing fn """
class DrawerList(ThemableBehavior, MDList):
def set_color_item(self, instance_item):
"""Called when tap on a menu item."""
# Set the color of the icon and text for the menu item.
for item in self.children:
if item.text_color == self.theme_cls.primary_color:
item.text_color = self.theme_cls.text_color
break
instance_item.text_color = self.theme_cls.primary_color
# print(f"inst:{instance_item.text_color}", f"thm_txt{self.theme_cls.text_color}",
# f"thm_prm{self.theme_cls.primary_color}")
class MenuScreen(Screen):
pass
# def on_enter(self, *args):
# self.ids.label_id.text = "Label text Updated"
class ProfileScreen(Screen):
pass
class UploadScreen(Screen):
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ProfileScreen(name='profile'))
sm.add_widget(UploadScreen(name='upload'))
class TestNavigationDrawer(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
icons_item = {
"folder": "My files",
"account-multiple": "Shared with me",
"star": "Starred",
"history": "Recent",
"checkbox-marked": "Shared with me",
"upload": "Upload",
}
for icon_name in icons_item.keys():
self.root.ids.content_drawer.ids.md_list.add_widget(
ItemDrawer(icon=icon_name, text=icons_item[icon_name])
)
TestNavigationDrawer().run()
所以有人知道如何在 KivyMD 中更改第一个屏幕标签或 on_enter 中的任何内容吗?
注意:取消对 # def on_enter(self, *args): # self.ids.label_id.text = "Label text Updated"
的注释。
它会显示错误。
我遇到了同样的问题。
错误似乎从这里开始:sm.add_widget(MenuScreen(name='menu'))
在将 class MenuScreen
添加到屏幕管理器时,会调用 on_enter。
这通常可以通过在顶部添加 Builder 来解决,但对于 KivyMD 我认为这是不可能的。
我还没有完全找到答案,但找到了解决方法(必须以某种方式 运行 应用程序)。
第 1 步:删除这些行:
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ProfileScreen(name='profile'))
sm.add_widget(UploadScreen(name='upload'))
像这样编辑 kv 程序:
Screen:
ScreenManager:
MenuScreen:
name:"menu"
ProfileScreen:
name:"profile"
UploadScreen:
name:"upload"
您可以在 python 程序的任何屏幕管理器 class 中使用 self.parent.current = "screen_name"
而不是 sm.current = "screen_name
。
而且,如果您需要在布局内部更改屏幕,而布局位于其他布局内部,那么...您可以使用 MDApp.get_running_app().root.ids.screen_manger.current = "screen_name"
而不是使用 self.parent.parent...
第 2 步:为避免第一个屏幕出现 on_enter 问题,请创建一个仅在应用程序启动时显示的徽标屏幕,如下所示:
在python程序中添加这个
class HomeScreen(Screen):
pass
并像这样编辑 Kv 程序:
Screen:
ScreenManager:
HomeScreen:
name:"home"
MenuScreen:
name:"menu"
ProfileScreen:
name:"profile"
UploadScreen:
name:"upload"
并将其添加到 kv-program
<HomeScreen>:
BoxLayout:
Button:
size:self.size
on_press:
root.manager.current = "menu"
您可以在按钮上添加图像或动画。
下面给出的是来自https://github.com/attreyabhatt/KivyMD-Basics/blob/master/13%20-%20Switching%20Screens/main.py
的kivyMD屏幕管理器程序我已经把它添加到KivyMD的官方导航抽屉程序https://kivymd.readthedocs.io/en/latest/components/navigation-drawer/index.html中
该程序运行良好,但我想使用 on_enter 函数更改 MenuScreen 中的文本。
我在class MenuScreen
里面评论了def on_enter
。
如果我们 运行 它取消注释显示此错误:
Traceback (most recent call last):
File "kivy\properties.pyx", line 861, in kivy.properties.ObservableDict.__getattr__
KeyError: 'label_id'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/kivy_prj1/kivy_mainmd/nav_screen.py", line 170, in <module>
sm.add_widget(MenuScreen(name='menu'))
File "C:\Users\Administrator\pyenv\lt_kivyvirt\lib\site-packages\kivy\uix\screenmanager.py", line 997, in add_widget
self.current = screen.name
File "kivy\properties.pyx", line 498, in kivy.properties.Property.__set__
File "kivy\properties.pyx", line 545, in kivy.properties.Property.set
File "kivy\properties.pyx", line 600, in kivy.properties.Property.dispatch
File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1154, in kivy._event.EventObservers._dispatch
File "C:\Users\Administrator\pyenv\lt_kivyvirt\lib\site-packages\kivy\uix\screenmanager.py", line 1062, in on_current
screen.dispatch('on_enter')
File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
File "C:/Users/Administrator/PycharmProjects/kivy_prj1/kivy_mainmd/nav_screen.py", line 156, in on_enter
self.ids.label_id.text = "Label text Updated"
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
'label_id'是我要改标签的id。
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty, ListProperty
from kivymd.app import MDApp
from kivymd.theming import ThemableBehavior
from kivymd.uix.list import OneLineIconListItem, MDList
from kivy.uix.screenmanager import ScreenManager, Screen
KV = '''
# Menu item in the DrawerList list.
<ItemDrawer>:
theme_text_color: "Custom"
on_release: self.parent.set_color_item(self)
IconLeftWidget:
id: icon
icon: root.icon
theme_text_color: "Custom"
text_color: root.text_color
<ContentNavigationDrawer>:
orientation: "vertical"
padding: "8dp"
spacing: "8dp"
AnchorLayout:
anchor_x: "left"
size_hint_y: None
height: avatar.height
Image:
id: avatar
size_hint: None, None
size: "56dp", "56dp"
source: "data/logo/kivy-icon-256.png"
MDLabel:
text: "KivyMD library"
font_style: "Button"
size_hint_y: None
height: self.texture_size[1]
MDLabel:
text: "kivydevelopment@gmail.com"
font_style: "Caption"
size_hint_y: None
height: self.texture_size[1]
ScrollView:
DrawerList:
id: md_list
Screen:
ScreenManager:
MenuScreen:
ProfileScreen:
UploadScreen:
NavigationLayout:
ScreenManager:
Screen:
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: "Navigation Drawer"
elevation: 10
left_action_items: [['menu', lambda x: nav_drawer.toggle_nav_drawer()]]
Widget:
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
id: content_drawer
<MenuScreen>:
name: 'menu'
MDRectangleFlatButton:
text: 'Profile'
pos_hint: {'center_x':0.5,'center_y':0.6}
on_press: root.manager.current = 'profile'
MDRectangleFlatButton:
text: 'Upload'
pos_hint: {'center_x':0.5,'center_y':0.5}
on_press: root.manager.current = 'upload'
MDLabel:
id:label_id
text: 'update this at on enter'
pos_hint: {'center_x':0.5,'center_y':0.4}
halign: 'center'
<ProfileScreen>:
name: 'profile'
MDLabel:
text: 'Profile'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.1}
on_press: root.manager.current = 'menu'
<UploadScreen>:
name: 'upload'
MDLabel:
text: 'Upload'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.1}
on_press: root.manager.current = 'menu'
'''
class ContentNavigationDrawer(BoxLayout):
pass
class ItemDrawer(OneLineIconListItem):
icon = StringProperty()
text_color = ListProperty((0, 0, 0, 1))
"""Instead of just giving MDList in kv file give DrawerList for adding the ThemableBehavior with it and created color
changing fn """
class DrawerList(ThemableBehavior, MDList):
def set_color_item(self, instance_item):
"""Called when tap on a menu item."""
# Set the color of the icon and text for the menu item.
for item in self.children:
if item.text_color == self.theme_cls.primary_color:
item.text_color = self.theme_cls.text_color
break
instance_item.text_color = self.theme_cls.primary_color
# print(f"inst:{instance_item.text_color}", f"thm_txt{self.theme_cls.text_color}",
# f"thm_prm{self.theme_cls.primary_color}")
class MenuScreen(Screen):
pass
# def on_enter(self, *args):
# self.ids.label_id.text = "Label text Updated"
class ProfileScreen(Screen):
pass
class UploadScreen(Screen):
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ProfileScreen(name='profile'))
sm.add_widget(UploadScreen(name='upload'))
class TestNavigationDrawer(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
icons_item = {
"folder": "My files",
"account-multiple": "Shared with me",
"star": "Starred",
"history": "Recent",
"checkbox-marked": "Shared with me",
"upload": "Upload",
}
for icon_name in icons_item.keys():
self.root.ids.content_drawer.ids.md_list.add_widget(
ItemDrawer(icon=icon_name, text=icons_item[icon_name])
)
TestNavigationDrawer().run()
所以有人知道如何在 KivyMD 中更改第一个屏幕标签或 on_enter 中的任何内容吗?
注意:取消对 # def on_enter(self, *args): # self.ids.label_id.text = "Label text Updated"
的注释。
它会显示错误。
我遇到了同样的问题。
错误似乎从这里开始:sm.add_widget(MenuScreen(name='menu'))
在将 class MenuScreen
添加到屏幕管理器时,会调用 on_enter。
这通常可以通过在顶部添加 Builder 来解决,但对于 KivyMD 我认为这是不可能的。
我还没有完全找到答案,但找到了解决方法(必须以某种方式 运行 应用程序)。
第 1 步:删除这些行:
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ProfileScreen(name='profile'))
sm.add_widget(UploadScreen(name='upload'))
像这样编辑 kv 程序:
Screen:
ScreenManager:
MenuScreen:
name:"menu"
ProfileScreen:
name:"profile"
UploadScreen:
name:"upload"
您可以在 python 程序的任何屏幕管理器 class 中使用 self.parent.current = "screen_name"
而不是 sm.current = "screen_name
。
而且,如果您需要在布局内部更改屏幕,而布局位于其他布局内部,那么...您可以使用 MDApp.get_running_app().root.ids.screen_manger.current = "screen_name"
self.parent.parent...
第 2 步:为避免第一个屏幕出现 on_enter 问题,请创建一个仅在应用程序启动时显示的徽标屏幕,如下所示:
在python程序中添加这个
class HomeScreen(Screen):
pass
并像这样编辑 Kv 程序:
Screen:
ScreenManager:
HomeScreen:
name:"home"
MenuScreen:
name:"menu"
ProfileScreen:
name:"profile"
UploadScreen:
name:"upload"
并将其添加到 kv-program
<HomeScreen>:
BoxLayout:
Button:
size:self.size
on_press:
root.manager.current = "menu"
您可以在按钮上添加图像或动画。