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
Related
i have been working on a python app using kivy and firebase authentication.. following youtube tutorials really....
i can get it so when the button is pressed on the signup screen and there is a valid email and password .. the user is created in firebase realtime db and it prints the idToken
however, when the user enters an invalid email password the code errors which i have used the Try and Except.. but i cant for the life of me link that Except to my .kv file where i have the label with id:login_message for the error message to be shown on the screen.
by chucking in some random letters into the signup inputs.. i can get it to print invalid
enter image description here
code is below...
what goes under the except in the class MyFirebaseSignup: and in the except: to print the label with id: login_message in the signup.kv file
LoginSignup.py
import pyrebase
from kivy.core.text import LabelBase
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen,ScreenManager
from kivymd.app import MDApp
from kivy.app import App
import requests
import json
Window.size = (310, 580)
config = {
"apiKey": "AIzaSyB8f5Py7E60rlCtpAaqXzpmWSgHN9vxfrc",
"authDomain": "fir-python-demo-39212.firebaseapp.com",
"databaseURL": "https://fir-python-demo-39212-default-rtdb.firebaseio.com",
"storageBucket": "fir-python-demo-39212.appspot.com",
}
firebase = pyrebase.initialize_app(config)
auth = firebase.auth()
class MyFirebaseSignup:
def sign_up(self, username, email, password, login_message=None):
try:
user = auth.create_user_with_email_and_password(email, password)
data = {"email": email, "password": password, "idToken": True}
info = auth.get_account_info(user["idToken"])
auth.send_email_verification(user["idToken"])
password = data.get("password")
print("Successfully created account")
except:
print("Invalid")
#App.get_running_app().root.ids["signup_screen"].ids["signup_screen"].text = MyLabel ..... doesnt work
#app..... id: SignUpError ---- display error message on signin page
pass
class MyFirebaseLogin():
def Login(self, email, password):
try:
login = auth.sign_in_with_email_and_password(email, password)
print("Successfully Logged in")
except:
print("invalid")
pass
class MainScreen(Screen):
pass
class LoginScreen(Screen):
pass
class SignupScreen(Screen):
pass
class LoginSignup(MDApp):
def build(self):
screen_manager = ScreenManager()
screen_manager.add_widget(Builder.load_file("main.kv"))
screen_manager.add_widget(Builder.load_file("signup.kv"))
screen_manager.add_widget(Builder.load_file("login.kv"))
self.my_firebasesignup = MyFirebaseSignup()
self.my_firebaselogin = MyFirebaseLogin()
return screen_manager
if __name__ == "__main__":
LoginSignup().run()
signup.kv
<SignupScreen>:
MDScreen:
name: "signup"
id: signup
MDFloatLayout:
MDLabel:
id: SignUpError
font_size: "18sp"
pos_hint: {"center_x":.5,"center_y":.73}
halign: "center"
color: (1,0,0,1)
MDFloatLayout:
size_hint: .7,.07
pos_hint: {"center_x":.5,"center_y":.68}
TextInput:
id: login_username
hint_text: "Username"
size_hint_y: .75
pos_hint: {"center_x":.43,"center_y":.5}
MDFloatLayout:
pos_hint: {"center_x":.45,"center_y":.0}
size_hint_y: .03
md_bg_color: rgba(178,178,178,255)
MDFloatLayout:
size_hint: .7,.07
pos_hint: {"center_x":.5,"center_y":.56}
TextInput:
id: login_email
hint_text: "Email"
size_hint_y: .75
pos_hint: {"center_x":.43,"center_y":.5}
MDFloatLayout:
pos_hint: {"center_x":.45,"center_y":.0}
size_hint_y: .03
md_bg_color: rgba(178,178,178,255)
MDFloatLayout:
size_hint: .7,.07
pos_hint: {"center_x":.5,"center_y":.44}
TextInput:
id: login_password
hint_text: "Password"
Button:
text: "SIGNUP"
size_hint: .66, .065
pos_hint: {"center_x":.5,"center_y":.3}
background_color: 0,0,0,0
font_name: "BPoppins"
canvas.before:
Color:
rgb: rgba(52,0,231,255)
RoundedRectangle:
size: self.size
pos: self.pos
radius: [5]
on_release:
print("Sign up", login_email.text, login_password.text)
app.my_firebasesignup.sign_up(login_username.text,login_email.text,login_password.text)
youtube, google, random code
I am trying build an app in Python using Kivymd and i just started learning this kivymd framework so the problem i am facing is when i am trying to change screen from LoginScreen to HomeScreen, it raises error. I am unable to understand what's wrong in my code.
I wanted it to change screen to HomeScreen and then show the list on pressing button 'Join Chat'.
Here is the code:
main.py
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen,ScreenManager
from kivymd.uix.list import MDList, OneLineIconListItem,IconLeftWidget
class LoginScreen(Screen):
pass
class HomeScreen(Screen):
pass
class DemoApp(MDApp):
def build(self):
self.theme_cls.theme_style="Dark"
self.sm=ScreenManager()
self.sm.add_widget(LoginScreen(name="login"))
self.sm.add_widget(HomeScreen(name="home"))
screen=Builder.load_file("helper_file.kv")
return screen
def do_login(self):
self.sm.current = "home"
for i in range(20):
st_name="student "
list_item = OneLineIconListItem(text=f"student {str(i)}")
list_item.add_widget(IconLeftWidget(icon= "alpha-a-box"))
self.root.ids.users_lst.add_widget(list_item)
DemoApp().run()
helper_file.kv
ScreenManager:
LoginScreen:
HomeScreen:
<LoginScreen>:
name: "login"
Screen:
MDLabel:
text: "Demo App"
halign: "center"
pos_hint: {"center_x": .5, "center_y": .8}
theme_text_color: "Primary"
MDTextField:
hint_text: "Enter username"
helper_text: "to join the chat (test mode)"
helper_text_mode: "on_focus"
icon_right: "android"
icon_right_color: app.theme_cls.primary_color
pos_hint:{'center_x': 0.5, 'center_y': 0.5}
size_hint_x:None
width:311
MDRoundFlatButton:
text: "Join Chat"
pos_hint: {"center_x": .5, "center_y": .4}
on_release: app.do_login()
MDLabel:
text: "This is testing mode only"
halign: "center"
pos_hint: {"center_x": .5, "center_y": .2}
theme_text_color:"Hint"
<HomeScreen>:
name: "home"
Screen:
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Demo Chat Application"
ScrollView:
MDList:
id: users_lst
On running this, the login screen working well but on pressing the button 'Join Chat' it raises the following error:
self.root.ids.users_lst.add_widget(list_item)
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
| 1 |
class HomeScreen(Screen):
pass
<HomeScreen>:
name: "home"
Screen:
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Demo Chat Application"
ScrollView:
MDList:
id: users_lst
You have a screen which has a screen, that's not what you want to do.
<HomeScreen>:
name: "home"
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Demo Chat Application"
ScrollView:
MDList:
id: users_lst
#######################################################
#######################################################
| 2 |
Parent doesn't have access of the id of inner children children's. (Not clear I know, So I'm gonna give you a lot of print to help you understand).
def do_login(self):
self.root.current = "home"
for i in range(20):
st_name = "student "
list_item = OneLineIconListItem(text=f"student {str(i)}")
list_item.add_widget(IconLeftWidget(icon="alpha-a-box"))
print("this is my App:", self)
print("this is my ScreenManager:", self.sm)
print("this is my global app visual widget (which is equal to ScreenManager here):", self.root)
print("this is the ScreenManager's dictionnary containing the widgets referenced with their id:", self.root.ids)
print("this is the current Screen:",self.root.current_screen)
print("this is current Screen dictionnary containing the widgets referenced with their id:", self.root.current_screen.ids)
print("this is the actual MDList", self.root.current_screen.ids["users_lst"])
self.root.current_screen.ids["users_lst"].add_widget(list_item)
I'm very new at Kivy. I'm following an example at kivy docs where I came across this following code. bBut it's not working properly.
first.py
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
class LoginScreen(GridLayout):
pass
class MyApp(App):
def build(self):
return LoginScreen()
if __name__ == '__main__':
MyApp().run()
my.kv
#:kivy 2.0
<LoginScreen>:
f_username: username
f_password: password
GridLayout:
rows: 2
cols: 2
padding: 10
spacing: 10
Label:
text: "Username"
TextInput:
id: username
multiline: False
Label:
text: "Password"
TextInput:
id: password
password: True
multiline: False
This code works fine if i remove the LoginScreen class from both kivy and python file. Like
class MyApp(App):
def build(self):
return
and
#:kivy 2.0
f_username: username
f_password: password
GridLayout:
rows: 2
...
Can anyone help me to figure out what's happening?
class LoginScreen(GridLayout):
pass
This means that when you create an instance with the LoginScreen class, the instance becomes GridLayout.
# GridLayout
<LoginScreen>:
f_username: username
f_password: password
# Another GridLayout!
GridLayout:
...
The LoginScreen is already based on GridLayout, but you are trying to add another gridlayout to the class. In this case, rows and cols are not defined on the outmost gridlayout.
#:kivy 2.0
<LoginScreen>:
f_username: username
f_password: password
rows: 2
cols: 2
padding: 10
spacing: 10
Label:
text: "Username"
TextInput:
id: username
multiline: False
Label:
text: "Password"
TextInput:
id: password
password: True
multiline: False
Removing the duplicate layout will fix the problem.
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
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