KivyMD 'MDMenuItem' object has no attribute 'text' - python-3.x

I want to click MDMenuItem to get text or do something.
But an error say "AttributeError: 'MDMenuItem' object has no attribute 'text' "
.py file like this
class MDMenuItem(Widget):
pass
class MyScreen(Screen):
menu_items = [
{'viewclass': 'MDMenuItem',
'text': 'text1'},
{'viewclass': 'MDMenuItem',
'text': 'text2'},
]
def change_variable(self, value):
print("\nvalue=", value)
self.VARIABLE = value
print("\tself.VARIABLE=", self.VARIABLE)
.kv file like this:
#:import MDDropdownMenu kivymd.menu.MDDropdownMenu
#:import MDRaisedButton kivymd.button.MDRaisedButton
<MDMenuItem>:
on_release: root.change_variable(self.text)
<MyScreen>:
name: myscrn
MDRaisedButton:
size_hint: None, None
size: 3 * dp(48), dp(48)
text: 'MDButton'
opposite_colors: True
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
on_release: MDDropdownMenu(items=root.menu_items, width_mult=4).open(self)
What should I do?
Edit:
Thank you for your reply. In my case, this .py subprogram not content 'App'. I don't want to put the method into main.py because I want main.py to stay clean.(Just content import, builder.load_file, add_wiget...)
So I want to call method without use 'app.something'.
Can I use root.something or other methods to call change_variable and get text?

I removed class MDMenuItem and change "root.change_variable" to "app.root.get_screen('MyScreen').change_variable". It's work!!!
The "app.root" treated as "screen.manager" in this case. I don't know why but it just work.
.py
class MyScreen(Screen):
menu_items = [
{'viewclass': 'MDMenuItem',
'text': 'text1'},
{'viewclass': 'MDMenuItem',
'text': 'text2'},
]
def change_variable(self, value):
print("\nvalue=", value)
self.VARIABLE = value
print("\tself.VARIABLE=", self.VARIABLE)
.kv
#:import MDDropdownMenu kivymd.menu.MDDropdownMenu
#:import MDRaisedButton kivymd.button.MDRaisedButton
<MDMenuItem>:
on_release: app.root.get_screen("MyScreen").change_variable(self.text)

Note:
The following solution is using KivyMD version 0.1.2.
AttributeError
AttributeError: 'MDMenuItem' object has no attribute 'text'
The error was due wrong definition for class MDMenuItem. It was defined with an inheritance of a Widget which does not has the attribute, 'text'.
Actual Definition of MDMenuItem
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import ButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
class MDMenuItem(RecycleDataViewBehavior, ButtonBehavior, BoxLayout):
text = StringProperty()
Solution
There is no need to define class MDMenuItem in main.py. Remove it and the program will run.
Example
main.py
from kivy.app import App
from kivymd.theming import ThemeManager
from kivy.uix.screenmanager import Screen
class MyScreen(Screen):
VARIABLE = ""
menu_items = [
{'viewclass': 'MDMenuItem',
'text': 'text1'},
{'viewclass': 'MDMenuItem',
'text': 'text2'},
]
def change_variable(self, value):
print("\nvalue=", value)
self.VARIABLE = value
print("\tself.VARIABLE=", self.VARIABLE)
class MainApp(App):
title = "KivyMD MDDropdownMenu Demo"
theme_cls = ThemeManager()
def build(self):
return MyScreen()
if __name__ == "__main__":
MainApp().run()
main.kv
#:kivy 1.11.0
#:import MDDropdownMenu kivymd.menu.MDDropdownMenu
#:import MDRaisedButton kivymd.button.MDRaisedButton
<MDMenuItem>:
on_release: app.root.change_variable(self.text)
<MyScreen>:
name: 'myscrn'
MDRaisedButton:
size_hint: None, None
size: 3 * dp(48), dp(48)
text: 'MDButton'
opposite_colors: True
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
on_release: MDDropdownMenu(items=root.menu_items, width_mult=4).open(self)
Output

Related

Kivy No Screen with name

In my main.py:
class WelcomeScreen(Screen):
pass
class SignupScreen(Screen):
username = ObjectProperty(None)
def submit(self):
db.add_user(self.username.text)
self.reset()
self.root.current = "login"
def login(self):
self.reset()
self.current = "signup"
def reset(self):
self.username.text = ""
class LoginScreen(Screen):
pass
class WindowManager(ScreenManager):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Clock.schedule_once(self.screen_switch_signup, 2)
def screen_switch_signup(self, time):
self.current = 'signup'
db = DataBase()
class mainApp(App):
kv_directory = 'kv'
def build(self):
return WindowManager()
if __name__ == '__main__':
mainApp().run()
Then,my main.kv:
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
WindowManager:
name: "screen_manager"
transition: SlideTransition()
WelcomeScreen:
name: "welcome"
#: include kv/signupScreen.kv
manager: 'screen_manager'
SignupScreen:
name: "signup"
#: include kv/signupScreen.kv
manager: 'screen_manager'
LoginScreen:
name: "login"
#: include kv/loginScreen.kv
manager: 'screen_manager'
Finally, I have 3 kv files:
My signupScreen.kv
<SignupScreen>:
username: username
TextInput:
id: username
hint_text: "Username"
Button:
text: "SIGN UP"
on_release:
app.root.transition.direction = "right"
root.submit()
my loginScreen.kv
<LoginScreen>:
BoxLayout:
orientation: 'vertical'
Label:
id: email
text: "Your email"
Button
id: go_back_screen_1
text: 'Go back'
on_release:
app.root.current = 'signup'
root.manager.transition.direction = 'right'
And finally the welcomeScreen.kv
<WelcomeScreen>:
Label:
text: "Welcome"
When I launch, I get the error:
File "kivy_clock.pyx", line 218, in kivy._clock.ClockEvent.tick
File "\Git\main.py",
line 89, in screen_switch_signup
self.current = 'signup'
kivy.uix.screenmanager.ScreenManagerException: No Screen with name
"signup".
I'm pretty new to Kivy, so I don't understand what's happening here.
The architecture is like that:
* myApp
* main.py
* kv
* main.kv
* loginScreen.kv
* signupScreen.kv
* welcomeScreen.kv
Any one knows please?
I have found several moments that can raise the error:
Here kv_directory = 'kv' you tell where all of your kv files are located. It means there should be a directory kv in your project directory. Make sure you have this directory and all kv files in it.
You should use <WindowManager>: instead of WindowManager: in your main.kv because you want to define (discribe) WindowManager class but not to add it to your app.
These hints should fix your app
Edit: I didn't catch sight of you've added the architecture of your project. Then just do the second point

Kivymd mapview app not able to load image

My mapview app is not loading the image and I don't know why
Check and make sure your internet connection is working fast
Make sure you have "requests" module
Try out this example, make sure you have already installed all kivy_garden modules
Try this code:
import sys
from kivy.base import runTouchApp
from kivy.lang import Builder
if __name__ == '__main__' and __package__ is None:
from os import path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
root = Builder.load_string(
"""
#:import sys sys
#:import MapSource kivy_garden.mapview.MapSource
MapView:
lat: 50.6394
lon: 3.057
zoom: 13
map_source: MapSource(sys.argv[1], attribution="") if len(sys.argv) > 1 else "osm"
MapMarkerPopup:
lat: 50.6394
lon: 3.057
popup_size: dp(230), dp(130)
Bubble:
BoxLayout:
orientation: "horizontal"
padding: "5dp"
AsyncImage:
source: "http://upload.wikimedia.org/wikipedia/commons/9/9d/France-Lille-VieilleBourse-FacadeGrandPlace.jpg"
mipmap: True
Label:
text: "[b]Lille[/b]\\n1 154 861 hab\\n5 759 hab./km2"
markup: True
halign: "center"
"""
)
runTouchApp(root)

Kivymd Reference error when using MDToolbar

from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.screen import MDScreen
from kivymd.app import MDApp
KV = '''
<Screen3>
MDBoxLayout:
orientation:'vertical'
MDToolbar:
title: "Home"
left_action_items: [["menu", lambda x: app.callback()]]
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
ScrollView:
size_hint:0.8,0.7
do_scroll_x:False
do_scroll_y:True
GridLayout:
size_hint_y:None
height:self.minimum_height
cols:1
spacing:10
padding:10
id:gr
'''
Builder.load_string(KV)
class Screen3(MDScreen):
pass
class Test(MDApp):
def build(self):
screen_manager = ScreenManager()
screen_manager.add_widget(Screen3(name='screen3'))
return screen_manager
Test().run()
This is my basic code right now. For some reason the reference error is caused by the left_action_items option. When I remove it the code works. I honestly have no idea what causes this issue.

Kivymd on_release Button the action for next step with MDCard does not work

I'm trying to make the button click on_release: app.proximo () have the action to go to the next card MDFloatLayout, but I'm not getting it, could someone help me how could it work?
Below the main.py file, where to start the app, main.kv file, where is the main app and finally the dashboard.kv file where I am calling my card inside the app
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
class DashBoard(Screen):
pass
class FirstScreen(Screen):
pass
class Lavanderia(MDApp):
def build(self):
self.title="Texto Titulo"
self.theme_cls.primary_palette = "LightBlue"
return Builder.load_file("main.kv")
def proximo(self):
self.root.ids.carousel.load_next(mode="proximo")# Próximo Card
def fecharApp(self):
self.stop()# Fecha Aplicativo
Lavanderia().run()
#:import rgba kivy.utils.get_color_from_hex
#: include dashboard.kv
#: include firstscreen.kv
NavigationLayout:
id: nav_layout
ScreenManager:
Screen:
BoxLayout:
orientation:'vertical'
MDToolbar:
title: app.title
elevation:10
left_action_items:[["menu", lambda x: nav_drawer.set_state()]]
ScreenManager:
id: screen_manager
DashBoard:
id:dashboard
name:"dashboard"
FirstScreen:
id:first_screen
name:"first_screen"
MDNavigationDrawer:
id: nav_drawer
BoxLayout:
orientation:'vertical'
padding:"8dp"
spacing:"8dp"
Image:
pos_hint:{"x":.24,"y":.0}
size_hint: None, None
size:dp(146), dp(158)
source:"images/logo.png"
ScrollView:
MDList:
OneLineIconListItem:
text:"Tela 1"
on_release:
screen_manager.current = "dashboard"
nav_drawer.set_state()
IconLeftWidget:
icon:"dishwasher"
OneLineIconListItem:
text:"Tela 2"
on_release:
screen_manager.current = "first_screen"
nav_drawer.set_state()
IconLeftWidget:
icon:"dishwasher"
<DashBoard>:
MDFloatLayout:
MDCard:
size_hint: dp(.45), dp(.8)
pos_hint:{"center_x": .5, "center_y": .5}
Carousel:
id:carousel
MDFloatLayout:
MDTextField:
hint_text:"Texto 1"
size_hint_x:dp(.8)
pos_hint:{"center_x": .5, "center_y": .48}
MDRaisedButton:
text: "Proximo"
size_hint_x:dp(.8)
pos_hint:{"center_x":.5,"center_y":.2}
on_release: app.proximo() # Proximo step
MDFloatLayout:
MDLabel:
text:"Texto Final Conclusão"
theme_text_color:"Custom"
bold:True
pos_hint:{"center_x":.68,"center_y":.5}
font_style:"H5"
MDRaisedButton:
text: "Fechar Aplicativo"
text_color:rgba("#00FF69")
size_hint_x:dp(.8)
pos_hint:{"center_x":.5,"center_y":.4}
md_bg_color:rgba("#333333")
on_release: app.fecharApp() #fechar Aplicativo
You are trying to ger the carrousel through the root screen, but it is inside the dashboard screen.
So you will have to navigate there first, and only then you can call your function.
def proximo(self):
dashboard = self.root.ids.dashboard
carousel = dashboard.ids.carousel
carousel.load_next(mode="proximo")
# Same as
# self.root.ids.dashboard.ids.carousel.load_next(mode="proximo")

How to change screen by calling a method in Python Kivy

I'm new to kivy and I want to change my screen by clicking the image. I used the ButtonBehavior and call the on_press method of my class ImageButton but I can't figure it out what code to put. I tried on_press: screen_manager.current = 'window1' on my kivy file but its not working
Python Code
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.behaviors import ButtonBehavior
class Window1(Screen):
pass
class Window2(Screen):
pass
class WindowManager(ScreenManager):
pass
class ImageButton(ButtonBehavior, Image):
def on_press(self):
# what to call
class Phone(FloatLayout):
pass
class MyApp(App):
def build(self):
return Phone()
if __name__ == '__main__':
MyApp().run()
kv file
<Phone>:
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
WindowManager:
id: screen_manager
size_hint: 1, 0.9
anchor_y: 'top'
transition: FadeTransition()
Window1:
Window2:
AnchorLayout:
anchor_x: 'center'
anchor_y: 'bottom'
BoxLayout:
canvas:
Color:
rgba: 228, 241, 254, 1
Rectangle:
size: self.size
orientation: 'horizontal'
size_hint: 1, .1
ImageButton:
source: 'pic1.png'
on_press: self.on_press()
ImageButton:
source: 'pic2.png'
on_press: self.on_press()
<Window1>:
name: 'window1'
Label:
text: 'Window1'
<Window2>:
name: 'window2'
Label:
text: 'Window2'
Some one help me on this.. what im missing is in my kv file i should put
on_press: app.root.ids._screen_manager.current = 'window1'
Here is the explanation
When the kv code is parsed, the id fields go into a dict called ids, that stores pointers to the widget objects.
Each kivy rule has a sperate name space for ids.
Breaking it down:
app.root.ids.screen_manager
app is your app
root is the root widget, Phone
ids is the dict of ids defined at the root level
Credit for Elliot Garbus

Resources