Reputation: 72
Give below is the kivyMD screen manager program from https://github.com/attreyabhatt/KivyMD-Basics/blob/master/13%20-%20Switching%20Screens/main.py
and I have added it to the official navigation drawer program https://kivymd.readthedocs.io/en/latest/components/navigation-drawer/index.html of KivyMD.
This program works perfectly, but I want to change the text in the MenuScreen with the on_enter function.
I have commented the def on_enter
inside class MenuScreen
.
If we run it uncommented shows this error:
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' is the id of my label that is to be changed.
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: "[email protected]"
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()
So anybody knows how to change the first screens label or anything from on_enter in KivyMD?
Note: Uncomment the # def on_enter(self, *args): # self.ids.label_id.text = "Label text Updated"
this.
It will show the error.
Upvotes: 0
Views: 1579
Reputation: 71
I haven't exactly find an answer, but found a way around(have to run app somehow).
Step 1: Remove these lines:
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ProfileScreen(name='profile'))
sm.add_widget(UploadScreen(name='upload'))
edit the kv-program like this:
Screen:
ScreenManager:
MenuScreen:
name:"menu"
ProfileScreen:
name:"profile"
UploadScreen:
name:"upload"
You can use self.parent.current = "screen_name"
inside any Screen manager class in the python program instead of sm.current = "screen_name
.
And if you needed to change screen inside of a layout which is inside of other and so.. instead of using self.parent.parent...
you can use MDApp.get_running_app().root.ids.screen_manger.current = "screen_name"
Step2: To avoid on_enter problem for the first screen create a logo screen that show up only at the start of application like this:
Add this in python program
class HomeScreen(Screen):
pass
and edit Kv-program like this:
Screen:
ScreenManager:
HomeScreen:
name:"home"
MenuScreen:
name:"menu"
ProfileScreen:
name:"profile"
UploadScreen:
name:"upload"
and add this to the kv-program
<HomeScreen>:
BoxLayout:
Button:
size:self.size
on_press:
root.manager.current = "menu"
You can add image or animation on the button.
Upvotes: 1
Reputation: 71
I am having the same problem.
It would seems like the error starts here : sm.add_widget(MenuScreen(name='menu'))
while adding the class MenuScreen
to the screen manager the on_enter is evoked.
This would usually solved by adding the Builder at the top, but for KivyMD i don't think it is not possible.
Upvotes: 2