AssertionError in the kivymd - python

I M trying to add screen inside the screen manager but giving error of assertion when assigning navigation drawer in a screen manager.
This is the Error i am facing :
self._apply_rule(
File "/home/hp/.local/lib/python3.8/site-packages/kivy/lang/builder.py", line 559, in _apply_rule
assert(rule not in self.rulectx)
AssertionError
This is my Code:
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
screen_helper = """
ScreenManager:
MenuScreen:
ProfileScreen:
ContentNavigationDrawer:
<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'
<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'
<ContentNavigationDrawer>:
name : 'upload'
ScrollView:
MDList:
OneLineListItem:
text: "Screen 1"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 1"
OneLineListItem:
text: "Screen 2"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 2"
Screen:
MDToolbar:
id: toolbar
pos_hint: {"top": 1}
elevation: 10
title: "MDNavigationDrawer"
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
NavigationLayout:
x: toolbar.height
ScreenManager:
id: screen_manager
Screen:
name: "scr 1"
MDLabel:
text: "Screen 1"
halign: "center"
Screen:
name: "scr 2"
MDLabel:
text: "Screen 2"
halign: "center"
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
screen_manager: screen_manager
nav_drawer: nav_drawer
"""
class MenuScreen(Screen):
pass
class ProfileScreen(Screen):
pass
class ContentNavigationDrawer(Screen):
screen_manager = ObjectProperty()
nav_drawer = ObjectProperty()
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ProfileScreen(name='profile'))
sm.add_widget(ContentNavigationDrawer(name='upload'))
class DemoApp(MDApp):
def build(self):
screen = Builder.load_string(screen_helper)
return screen
DemoApp().run()

I believe the problem is that your rule in screen_helper:
<ContentNavigationDrawer>:
includes:
ContentNavigationDrawer:
screen_manager: screen_manager
nav_drawer: nav_drawer
That rule combination tells kivy that whenever it creates a ContentNavigationDrawer it should create another ContentNavigationDrawer as a child of the first. Then it would try to apply the original <ContentNavigationDrawer>: again, creating a third ContentNavigationDrawer, applying the rule again to create a fourth, and so on. This would create an infinite loop. Kivy uses the assertion to avoid such loops. So, you just cannot use a rule that would create such a loop.

Related

KivyMD ContentNavigationDrawer acces Textvariable from Screen

I'm quite new to Python and Kivy.
I'm Building an app for Android.
I'm using a modifyed version of the Navigation Drawer example from here: https://kivymd.readthedocs.io/en/latest/components/navigationdrawer/
I want to get the Value of the Textfield from scr 1 vorname_input. I get this before without switchable screens. But i can't figure out how it works with the different screens. I googled for several hours and tryed so much things but i can't get it working.
If I use print (self.root.ids.vorname_input.text) its empty.
KV File:
<ContentNavigationDrawer>
MDList:
OneLineListItem:
text: "Screen 1"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 1"
OneLineListItem:
text: "Screen 2"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 2"
MDScreen:
MDTopAppBar:
pos_hint: {"top": 1}
elevation: 4
title: "MDNavigationDrawer"
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
MDNavigationLayout:
MDScreenManager:
id: screen_manager
MDScreen:
name: "scr 1"
BoxLayout:
orientation: "vertical"
#size: root.width, root.height
spacing: "25dp"
padding: [12, 80, 12, 12]
MDTextField:
id: vorname_input
hint_text: "Vorname"
mode: "rectangle"
multiline: False
icon_left: 'account'
helper_text_mode: 'on_error'
helper_text: ''
mode: "fill"
fill_color: 0, 0, 0, .4
MDFlatButton:
#size_hint: (1, .5)
font_size: 25
text: "Kunde Speichern"
on_press: app.save_cust_to_db()
md_bg_color: app.theme_cls.primary_color
theme_text_color: "Custom"
text_color: 0.93, 0.93, 0.93, 1
MDScreen:
name: "scr 2"
MDLabel:
text: "Screen 2"
halign: "center"
MDNavigationDrawer:
id: nav_drawer
radius: (0, 16, 16, 0)
ContentNavigationDrawer:
screen_manager: screen_manager
nav_drawer: nav_drawer
Py File:
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
from kivymd.uix.scrollview import MDScrollView
class ContentNavigationDrawer(MDScrollView):
screen_manager = ObjectProperty()
nav_drawer = ObjectProperty()
class Example(MDApp):
def build(self):
self.theme_cls.primary_palette = "Orange"
self.theme_cls.theme_style = "Dark"
return Builder.load_string(KV)
def save_cust_to_db(self):
print (self.root.ids.vorname_input.text)
Example().run()
I found my mistake. In the KV file downwards i had another label with the same id. So it gets always overwritten and printet nothing because this textinputfield was empty.
It was a common copy and paste misstake :)

KivyMD Update Label Text

I´m trying to figure out, how to get the selected date from my Datepicker into a Label in the kv file. Maybe someone can help me. Greetings
The code from py file
from tkinter import Button
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.uix.picker import MDDatePicker
from datetime import datetime
from kivy.properties import StringProperty
class Demo(ScreenManager):
pass
class Main(MDApp):
def build(self):
Builder.load_file("layout.kv")
return Demo()
def on_save(self, instance, value, date_range):
print(instance, value, date_range)
fristbeginn = StringProperty(value)
def on_cancel(self, instance, value):
'''Events called when the "CANCEL" dialog box button is clicked.'''
def show_date_picker(self):
date_dialog = MDDatePicker()
date_dialog.bind(on_save=self.on_save, on_cancel=self.on_cancel)
date_dialog.open()
#class DatePicker(Button):
class Content(BoxLayout):
nav_drawer = ObjectProperty()
manager = ObjectProperty()
Main().run()
The code from .kv file:
<Content>:
ScrollView:
MDList:
OneLineListItem:
text: "Screen 1"
on_release:
root.nav_drawer.set_state("close")
root.manager.current = "screen1"
OneLineListItem:
text: "Screen 2"
on_release:
root.nav_drawer.set_state("close")
root.manager.current = "screen2"
OneLineListItem:
text: "Screen 3"
on_release:
root.nav_drawer.set_state("close")
root.manager.current = "screen3"
OneLineListItem:
text: "Screen 4"
on_release:
root.nav_drawer.set_state("close")
root.manager.current = "screen4"
OneLineListItem:
text: "Screen 5"
on_release:
root.nav_drawer.set_state("close")
root.manager.current = "screen5"
<Demo>:
Screen:
adaptive_size: True
MDToolbar:
pos_hint: {"top":1}
title: "Menü"
elevation: 8
left_action_items:[["menu", lambda x: nav_drawer.set_state("open") ]]
MDNavigationDrawer:
id: nav_drawer
Content:
nav_drawer: nav_drawer
manager: screen_manager
MDNavigationLayout:
ScreenManager:
id: screen_manager
Screen:
name: "screen1"
MDLabel:
text: "Guten Tag Bildschirm 1"
halign: "center"
Screen:
name: "screen2"
MDBoxLayout:
adaptive_size: True
size_hint: .8, None
orientation: "vertical"
pos_hint: {'center_x': .7, 'center_y': 0.55}
spacing: '20dp'
padding: ('20dp', '20dp', '20dp', '20dp')
MDLabel:
text: "Berechnung einer Frist nach §183 BGB:"
halign: "left"
font_style: "Subtitle1"
#pos_hint: {'center_x': 0.5, 'center_y': 0.5}
MDLabel:
text:""
halign: "center"
MDLabel:
text: "Wählen sie den Tag des Fristbeginn aus"
halign: "left"
font_style: "Subtitle2"
MDRaisedButton:
text: "Datum wählen"
on_release:app.show_date_picker()
MDLabel:
id: fristbeginn
text: root.fristbeginn
halign: "left"
font_style: "Subtitle2"
MDRaisedButton:
text: "MDRaised Button"
MDRaisedButton:
text: "MDRaised Button"
MDRaisedButton:
text: "MDRaised Button"
MDRaisedButton:
text: "MDRaised Button"
MDRaisedButton:
text: "MDRaised Button"
Screen:
name: "screen3"
MDLabel:
text: "Guten Tag Bildschirm 3"
halign: "center"
Screen:
name: "screen4"
MDLabel:
text: "Guten Tag Bildschirm 4"
halign: "center"
Screen:
name: "screen5"
MDLabel:
text: "Guten Tag Bildschirm 5"
halign: "center"
You are close. Using a StringProperty is a good idea, but you must define a StringProperty inside a class, but not within a method. Since your kv references root.fristbeginn, that property must be in the Demo class, like this:
class Demo(ScreenManager):
fristbeginn = StringProperty()
And the on_save() method becomes:
def on_save(self, instance, value, date_range):
print(instance, value, date_range)
# fristbeginn = StringProperty(value)
self.root.fristbeginn = str(value)

KivyMD NavigationDrawer slides over multiple screens

Using KivyMD MDNavigationLayout, I'm trying to make a navigation drawer for an app! I did it that way, however my navigation drawer now moves across several screens! I only want it to appear on my HomeScreen, not my MenuScreen!
Thank you so much for what you've done.
KV Code:
MDScreen:
MDNavigationLayout:
ScreenManager:
HomeScreen:
id: home
MDBoxLayout:
orientation: 'vertical'
MDToolbar:
title: 'Navigation Drawer'
left_action_items: [['menu', lambda x: nav_drawer.set_state('toggle')]]
Widget:
MenuScreen:
id: menu
MDNavigationDrawer:
id: nav_drawer
<HomeScreen>:
name: 'home_screen'
MDLabel:
id: label
text: 'Home Screen'
halign: 'center'
MDRaisedButton:
text: 'Menu Screen'
pos_hint: {'center_x':0.5, 'center_y':0.4}
on_press: root.manager.current = 'menu_screen'
<MenuScreen>:
name: 'menu_screen'
MDLabel:
text: f'Menu Screen from Home Screen'
halign: 'center'
MDRaisedButton:
text: 'Home Screen'
pos_hint: {'center_x':0.5, 'center_y':0.4}
on_press: root.manager.current = 'home_screen'
HomeScreen:
MenuScreen:
The NavigationDrawer is a widget that is designed to work across many screens. It will show up across multiple screens. If we take a closer look at you.kv file we can figure out why. Notice how the MDNavigationLayout is above your Screenmanager. This means that all the Screens that come under your ScreenManager(A widget that basically manages your screen and allows you to switch between them easily) will be shown in the NavigationLayout.
There isn't really a way to exclude a Screen from showing the NavigationDrawer as the widget was designed to show itself across all screens that are under it
As can be seen here in the docs examples:
https://kivymd.readthedocs.io/en/0.104.1/components/navigation-drawer/[kivymd docs]1
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
KV = '''
<ContentNavigationDrawer>:
ScrollView:
MDList:
OneLineListItem:
text: "Screen 1"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 1"
OneLineListItem:
text: "Screen 2"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 2"
MDScreen:
MDToolbar:
id: toolbar
pos_hint: {"top": 1}
elevation: 10
title: "MDNavigationDrawer"
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
MDNavigationLayout:
x: toolbar.height
ScreenManager:
id: screen_manager
MDScreen:
name: "scr 1"
MDLabel:
text: "Screen 1"
halign: "center"
MDScreen:
name: "scr 2"
MDLabel:
text: "Screen 2"
halign: "center"
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
screen_manager: screen_manager
nav_drawer: nav_drawer
'''
class ContentNavigationDrawer(MDBoxLayout):
screen_manager = ObjectProperty()
nav_drawer = ObjectProperty()
class TestNavigationDrawer(MDApp):
def build(self):
return Builder.load_string(KV)
TestNavigationDrawer().run()
https://kivymd.readthedocs.io/en/latest/components/navigationdrawer/#switching-screens-in-the-screenmanager-and-using-the-common-mdtoolbar

Python kivy update label text in different screens

I'm working on a kivy project. I have tested the kivymd navigation layout. I wonder how can I update the label in screen 1 and screen 2. eg, count from 1 to 100 when start button is pressed.
I have searched online about kivy update label like this:
update label
but the in kv string the screen is in "< >", while mine is "Screen:", and I have tried to create a function called Screen() but it is not wokring.
Can anyone please explain to me what does "< >" mean and how can I dynamically update the label in the kivymd navigation layout? thank you very much
code is here:
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
KV = '''
<ContentNavigationDrawer>:
<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:
MDList:
OneLineListItem:
text: "Screen 1"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 1"
OneLineListItem:
text: "Screen 2"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 2"
Screen:
MDToolbar:
id: toolbar
pos_hint: {"top": 1}
elevation: 10
title: "MDNavigationDrawer"
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
NavigationLayout:
x: toolbar.height
ScreenManager:
id: screen_manager
Screen:
name: "scr 1"
MDLabel:
text: "Screen 1"
halign: "center"
Screen:
name: "scr 2"
MDLabel:
text: "Screen 2"
halign: "center"
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
screen_manager: screen_manager
nav_drawer: nav_drawer
'''
class ContentNavigationDrawer(BoxLayout):
screen_manager = ObjectProperty()
nav_drawer = ObjectProperty()
class TestNavigationDrawer(MDApp):
def build(self):
return Builder.load_string(KV)
TestNavigationDrawer().run()
You can try with app.root.get_screen('scr1').funct() and make a function to change what you want

How to make a kivymd page navigation and insert some categories at the main menu?

I am very new with kivymd and I got the layout to the main menu, but I could not get how to create a navigation menu to redirect the user to Login page.
The main idea is to let the user click at the menu button to consult the different categories, but I have not found how to include these categories at the menu icon, can anyone help me on it?
from kivy.lang import Builder
from kivymd.app import MDApp
KV = """
BoxLayout:
# Will always be at the bottom of the screen.
MDBottomAppBar:
MDToolbar:
title: "Title"
icon: "cart-plus"
type: "bottom"
left_action_items: [["menu", lambda x: x]]
mode: "end"
"""
class Shop(MDApp):
def build(self):
return Builder.load_string(KV)
Shop().run()
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
KV = '''
<ContentNavigationDrawer>:
ScrollView:
MDList:
OneLineListItem:
text: "Screen 1"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 1"
OneLineListItem:
text: "Screen 2"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 2"
Screen:
MDToolbar:
id: toolbar
pos_hint: {"top": 1}
elevation: 10
title: "MDNavigationDrawer"
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
NavigationLayout:
x: toolbar.height
ScreenManager:
id: screen_manager
Screen:
name: "scr 1"
MDLabel:
text: "Screen 1"
halign: "center"
Screen:
name: "scr 2"
MDLabel:
text: "Screen 2"
halign: "center"
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
screen_manager: screen_manager
nav_drawer: nav_drawer
'''
class ContentNavigationDrawer(BoxLayout):
screen_manager = ObjectProperty()
nav_drawer = ObjectProperty()
class TestNavigationDrawer(MDApp):
def build(self):
return Builder.load_string(KV)
TestNavigationDrawer().run()
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
KV = '''
<ContentNavigationDrawer>:
ScrollView:
MDList:
OneLineListItem:
text: "Screen 1"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 1"
OneLineListItem:
text: "Screen 2"
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "scr 2"
Screen:
MDToolbar:
id: toolbar
pos_hint: {"top": 1}
elevation: 10
title: "MDNavigationDrawer"
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
MDNavigationLayout:
x: toolbar.height
ScreenManager:
id: screen_manager
Screen:
name: "scr 1"
MDLabel:
text: "Screen 1"
halign: "center"
Screen:
name: "scr 2"
MDLabel:
text: "Screen 2"
halign: "center"
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
screen_manager: screen_manager
nav_drawer: nav_drawer
'''
class ContentNavigationDrawer(BoxLayout):
screen_manager = ObjectProperty()
nav_drawer = ObjectProperty()
class TestNavigationDrawer(MDApp):
def build(self):
return Builder.load_string(KV)
TestNavigationDrawer().run()
for more information see the official documentation ok KivyMD
Hope this Helped you!

Categories

Resources