KivyMD - ScreenManager and ids - python

How's everyone doing? I am learning about KivyMD and ScreenManager and I have a little problem (and a big one). I was writing a program (like most beginners do) which would allow a user to log in or sign up (I was also practicing about sqlite3, but I don't have a problem with that).
First, I've tried to do everything in only one screen and it worked perfectly!
But now, when I try to use any function, I get:
_username = self.root.ids.my_username.text
AttributeError: 'super' object has no attribute '__getattr__'
The py file is:
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
import sqlite3
class MainMenu(Screen):
pass
class LogIn(Screen):
pass
class SignUp(Screen):
pass
class MainLogSignApp(MDApp):
def build(self):
# Connect to databse an create a cursor
conn = sqlite3.connect('user_pass.db')
c = conn.cursor()
c.execute("""CREATE TABLE if not exists user_name(
username text,
password text
)""")
conn.commit()
conn.close()
return Builder.load_file('mainlogsign.kv')
return sm
def submit_info(self):
'''If the info does not exist, it adds it to the table;
If it does, the function check if it is correct'''
_username = self.root.ids.my_username.text
_password = self.root.ids.my_password.text
# Connect and create cursor
conn = sqlite3.connect('user_pass.db')
c = conn.cursor()
# This should not be necesary, but it is here just in case I delete the table using the DELETE button.
c.execute("""CREATE TABLE if not exists user_name(
username text,
password text
)""")
c.execute("SELECT * FROM user_name WHERE username = (?)", (_username,))
already_in = c.fetchone()
if already_in and already_in[0]:
self.root.ids.my_message.text = already_in[0] + '\nUser already exists'
else:
c.execute("INSERT INTO user_name VALUES (?,?)", (_username, _password))
self.root.ids.my_message.text = 'User added successfully'
conn.commit()
conn.close()
self.root.ids.my_username.text = ''
self.root.ids.my_password.text = ''
# THERE ARE MORE FUNCTIONS, BUT THEY ALL HAVE THE SAME PROBLEM.
if __name__ == '__main__':
MainLogSignApp().run()
And the kivy file is:
ScreenManager:
MainMenu:
LogIn:
SignUp:
<MyTextField#MDTextFieldRound>:
font_size: 12
size_hint_x: 0.6
pos_hint: {'center_x': 0.5}
halign: 'center'
<MainMenu>:
name: 'main_menu'
BoxLayout:
orientation: 'vertical'
Label:
size_hint: .1, .3
MDRoundFlatButton:
text: 'LOG IN'
pos_hint: {'center_x': .5}
on_press:
root.manager.current = 'login'
root.manager.transition.direction = 'left'
Label:
size_hint: .1, .1
MDRoundFlatButton:
text: 'SIGN UP'
pos_hint: {'center_x': .5}
on_press:
root.manager.current = 'signup'
root.manager.transition.direction = 'left'
Label:
size_hint: .1, .3
<LogIn>:
name: 'login'
BoxLayout:
orientation: 'vertical'
MDLabel:
text: 'LOGIN'
halign: 'center'
Button:
id: my_label_l
text: 'DELETE'
size_hint: 0.6, 0.2
pos_hint: {'center_x': .5}
halign: 'center'
on_press: app.delete_record()
MyTextField:
id: my_username_l
hint_text: 'Enter your username'
icon_right: 'account'
MyTextField:
id: my_password_l
hint_text: 'Enter your password'
icon_right: 'eye-outline'
Button:
id: log_in
text: 'LOG IN'
size_hint: 0.6, 0.2
pos_hint: {'center_x': .5}
on_press: app.log_in()
Button:
id: show_button_l
text: 'Nothing'
size_hint: 0.6, 0.2
pos_hint: {'center_x': .5}
MDLabel:
id: my_message_l
text: ''
halign: 'center'
MDRectangleFlatIconButton:
icon: 'backspace-outline'
on_press:
root.manager.current = 'main_menu'
root.manager.transition.direction = 'right'
<SignUp>:
name: 'signup'
BoxLayout:
orientation: 'vertical'
MDLabel:
text: 'SIGNUP'
halign: 'center'
Button:
id: my_label
text: 'DELETE'
size_hint: 0.6, 0.2
pos_hint: {'center_x': .5}
halign: 'center'
on_press: app.delete_record()
MyTextField:
id: my_username
hint_text: 'Enter your username'
icon_right: 'account'
MyTextField:
id: my_password
hint_text: 'Enter your password'
icon_right: 'eye-outline'
Button:
id: submit_button
text: 'Submit info'
size_hint: 0.6, 0.2
pos_hint: {'center_x': .5}
on_press: app.submit_info()
Button:
id: show_button
text: 'Show records'
size_hint: 0.6, 0.2
pos_hint: {'center_x': .5}
on_press: app.show_info()
MDLabel:
id: my_message
text: ''
halign: 'center'
MDRectangleFlatIconButton:
icon: 'backspace-outline'
on_press:
root.manager.current = 'main_menu'
root.manager.transition.direction = 'right'
None of the functions work, so I'm guessing it has something to do with 'app.function()' or the ids, but it did work the first time. Maybe I have to use a different path, but I don't know.
As a small problem, when I write on the TextInput the hint text doesn't disappear. Any idea why?
Thanks!
BTW, you may notice the button 'DELETE' and 'SHOW RECORDS' and think they have nothing to do with a Login or SignUp program. You couldn't be more right!! So don't pay attention to them. I only added those button to work with sqlite3, but on a real app or site they wouldn't be there. Still, the problem is the same with any button.

Ok, I've solved the problem. I wrote the function submit_info into the SignUp class and change the app.submit_info() to root.submit_info() (in the kv file). Also, I had to remove every "root." in the function.
I hope this works if anybody gets the same problem.

Related

How do I turn the text that is inputed by a user into a kivyMD text box to a variable in python file?

Im relatively new to Kivy/KivyMD. I cant figure out how to take the values from the username and password text fields and turn them into variable in my python file when the sign up button is pressed.
Currently when the Signup button is clicked it just prints "clicked".
Any help would be greatly appreciated!
Below is my python file:
from kivymd.app import MDApp
from kivymd.uix.relativelayout import MDRelativeLayout
from kivy.lang import Builder
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen, SwapTransition
Builder.load_file('ALevelNEA.kv')
##Below are the classes for my different screens
class SignupScreen(Screen):
pass
class MenuScreen(Screen):
pass
class SigninScreen(Screen):
pass
## Below are the classes for my custom buttons, widgets and text fields
class PasswordField(MDRelativeLayout):
text = StringProperty()
hint_text = StringProperty()
pass
class EmailField(MDRelativeLayout):
text = StringProperty()
hint_text = StringProperty()
#email_field = ObjectProperty(None)
##Below is the code for my main app
class MainApp(MDApp):
def build(self):
sm = ScreenManager(transition= SwapTransition())
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SigninScreen(name = 'signin'))
sm.add_widget(SignupScreen(name='signup'))
return sm
def RecordCheck(self):
print("clicked")
def AddToRecord(self):
print("clicked")
if __name__ == '__main__':
MainApp().run()
Below is my KV file:
#Below are my different screens
#Below is the Menu Screen
<MenuScreen>:
Screen:
Image:
source: "Logonb.png"
size_hint_x: 0.4
size_hint_y: 0.6
allow_stretch: True
pos_hint: {"center_x": 0.5, "center_y": 0.6 }
MDFillRoundFlatButton:
id: SignIn
text: "Sign in with email"
pos_hint: {"center_x": 0.5, "center_y": 0.2}
md_bg_color: 0.3607, 0.3882, 1
size_hint: 0.225, 0
on_release:
root.manager.current = "signin"
MDRoundFlatButton:
text: "Sign up"
pos_hint: {"center_x": 0.5, "center_y": 0.12}
text_color: 0.3607, 0.3882, 1
line_color: 0, 0, 0
on_release:
root.manager.current = "signup"
MDLabel:
text: "by continuing you agree to the"
font_size: 15
halign: 'center'
pos_hint: {"center_y": 0.07}
MDTextButton:
text: "Terms and Conditions"
font_size: 15
pos_hint: {"center_x": 0.5, "center_y": 0.0525}
theme_text_color: "Custom"
text_color: 0.3607, 0.3882, 1
# Below is my sign in Screen
<SigninScreen>:
Screen:
MDIconButton:
icon: "keyboard-backspace"
pos_hint: {"center_x": 0.35, "center_y": 0.95}
on_release:
root.manager.current = "menu"
Image:
source: "LoginImage.png"
size_hint_x: 0.4
size_hint_y: 0.6
allow_stretch: True
pos_hint: {"center_x": 0.5, "center_y": 0.7 }
MDLabel:
text: "Sign in"
halign: "center"
pos_hint: {"center_x": 0.387, "center_y": 0.45}
font_size: 30
font_style: "H5"
EmailField:
hint_text: "Email ID"
pos_hint: {"center_x": 0.5, "center_y": 0.375}
size_hint_x: None
width: "250dp"
PasswordField:
size_hint_x: None
width: "250dp"
hint_text: "Password"
pos_hint: {"center_x": 0.5, "center_y": 0.3}
MDTextButton:
text: "Forgot password?"
font_size: 15
pos_hint: {"center_x": 0.62, "center_y": 0.255}
theme_text_color: "Custom"
text_color: 0.3607, 0.3882, 1
MDFillRoundFlatButton:
text: "Sign in"
pos_hint: {"center_x": 0.5, "center_y": 0.2}
md_bg_color: 0.3607, 0.3882, 1
size_hint: 0.225, 0
on_release: app.RecordCheck()
MDLabel:
text: "by continuing you agree to the"
font_size: 15
halign: 'center'
pos_hint: {"center_y": 0.15}
MDTextButton:
text: "Terms and Conditions"
font_size: 15
pos_hint: {"center_x": 0.5, "center_y": 0.1325}
theme_text_color: "Custom"
text_color: 0.3607, 0.3882, 1
#Below is the sign up screen
<SignupScreen>:
Screen:
EmailField:
hint_text: "Email"
pos_hint: {"center_x": 0.5, "center_y": 0.375}
size_hint_x: None
width: "250dp"
on_text: root.email = self.text
PasswordField:
size_hint_x: None
width: "250dp"
hint_text: "Password"
pos_hint: {"center_x": 0.5, "center_y": 0.3}
on_text: root.password = self.text
MDRoundFlatButton:
text: "Sign up"
pos_hint: {"center_x": 0.5, "center_y": 0.12}
text_color: 0.3607, 0.3882, 1
line_color: 0, 0, 0
on_release: app.AddToRecord()
#Custom buttons and text fields are located below
<PasswordField>:
size_hint_y: None
height: text_field.height
MDTextField:
id: text_field
hint_text: root.hint_text
text: root.text
password: True
icon_left: "lock"
MDIconButton:
icon: "eye-off"
pos_hint: {"center_y": .5}
pos: text_field.width - self.width + dp(8), 0
theme_text_color: "Hint"
on_release:
self.icon = "eye" if self.icon == "eye-off" else "eye-off"
text_field.password = False if text_field.password is True else True
<EmailField>:
size_hint_y: None
height: email_field.height
MDTextField:
id: email_field
hint_text: root.hint_text
text: root.text
icon_left: "email"
Add id attribute both to email and password widgets:
EmailField:
id: email_widget
PasswordField:
id: pass_widget
And you can pass any additional parameters to your method, for example replace:
on_release: app.AddToRecord()
with
on_release: app.AddToRecord(root.ids.email_widget.ids.email_field.text, root.ids.pass_widget.ids.text_field.text)
then change your AddToRecord method definition to:
def AddToRecord(self, email, passw):
print("clicked")
print(f'email: {email}, password: {passw}')
For the email, you can use the get_screen() method of ScreenManager and some ids to access the MDTextField that contains the text. First, add an id to the EmailField:
EmailField:
id: emailfield # added id
hint_text: "Email ID"
pos_hint: {"center_x": 0.5, "center_y": 0.375}
size_hint_x: None
width: "250dp"
Then use that new id and get_screen() to access the MDTextField in your RecordCheck() method:
def RecordCheck(self):
print("clicked")
signinScreen = self.root.get_screen('signin')
email = signinScreen.ids.emailfield.ids.email_field.text
print('email:', email)
Very similar approach can be used to access the password.

How do I set up a scroll view Kivy?

I'm relatively new to Kivy/KivyMD. I'm currently trying to figure out how to set up a scroll view for one of my screens. As far as I'm aware in order to use a scroll view I need to use a grid layout. Whenever I do this, all the items move to the left of the screen and some of them disappear completely.
Below is an image of the screen I need more space for:
Not enough space
Below is my python file for what I attempted:
import sqlite3
from kivymd.app import MDApp
from kivymd.uix.relativelayout import MDRelativeLayout
from kivy.lang import Builder
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen, SwapTransition
from kivy.uix.scrollview import ScrollView
Builder.load_file('ALevelNEA.kv')
##Below are the classes for my different screens
class SignupScreen(Screen):
pass
class MenuScreen(Screen):
pass
class SigninScreen(Screen, ScrollView):
pass
## Below are the classes for my custom buttons, widgets and text fields
class NameField(MDRelativeLayout):
text = StringProperty()
hint_text = StringProperty()
pass
class ConfirmPasswordField(MDRelativeLayout):
text = StringProperty()
hint_text = StringProperty()
pass
class NameField(MDRelativeLayout):
text = StringProperty()
hint_text = StringProperty()
pass
class PasswordField(MDRelativeLayout):
text = StringProperty()
hint_text = StringProperty()
pass
class EmailField(MDRelativeLayout):
text = StringProperty()
hint_text = StringProperty()
#email_field = ObjectProperty(None)
##Below is the code for my main app
class MainApp(MDApp):
def build(self):
sm = ScreenManager(transition= SwapTransition())
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SigninScreen(name = 'signin'))
sm.add_widget(SignupScreen(name='signup'))
return sm
def RecordCheck(self):
print("clicked")
def AddToRecord(self, email, passw):
NewEmail = email
NewPassword = passw
# Connect to or create a new database
conn = sqlite3.connect('example.db')
# Create a cursor object to execute SQL commands
cursor = conn.cursor()
# Create a table to store the records
cursor.execute('''CREATE TABLE IF NOT EXISTS users (email TEXT, password TEXT)''')
# Insert the user's information into the table
cursor.execute("INSERT INTO users (email, password) VALUES (?, ?)", (NewEmail, NewPassword))
# Committing the changes and closing the connection to the database file
conn.commit()
conn.close()
if __name__ == '__main__':
MainApp().run()
Below is the section of my KV file which is relevant for what I attempted:
<SignupScreen>:
ScrollView:
GridLayout:
cols: 1
size_hint_y: None
height: self.minimum_height
padding: dp(10)
spacing: dp(10)
Image:
source: "Images/RegisterImage.png"
size_hint_x: 0.4
size_hint_y: 0.6
allow_stretch: True
pos_hint: {"center_x": 0.5, "center_y": 0.8 }
MDIconButton:
icon: "keyboard-backspace"
pos_hint: {"center_x": 0.35, "center_y": 0.95}
on_release:
root.manager.current = "menu"
EmailField:
id: email_widget
hint_text: "Email"
pos_hint: {"center_x": 0.5, "center_y": 0.55}
size_hint_x: None
width: "250dp"
NameField:
id: name_widget
hint_text: "Name"
pos_hint: {"center_x": 0.5, "center_y": 0.45}
size_hint_x: None
width: "250dp"
PasswordField:
id: passw_widget
size_hint_x: None
width: "250dp"
hint_text: "Password"
pos_hint: {"center_x": 0.5, "center_y": 0.35}
ConfirmPasswordField:
id: Cpass_widget
size_hint_x: None
width: "250dp"
hint_text: "Confirm Password"
pos_hint: {"center_x": 0.5, "center_y": 0.25}
MDRoundFlatButton:
text: "Sign up"
pos_hint: {"center_x": 0.5, "center_y": 0.15}
text_color: 0.3607, 0.3882, 1
line_color: 0, 0, 0
#on_release: app.AddToRecord()
on_release:
app.AddToRecord(root.ids.email_widget.ids.email_field.text, root.ids.passw_widget.ids.text_field.text)
MDLabel:
text: "by continuing you agree to the"
font_size: 15
halign: 'center'
pos_hint: {"center_y": 0.1}
MDTextButton:
text: "Terms and Conditions"
font_size: 15
pos_hint: {"center_x": 0.5, "center_y": 0.0825}
theme_text_color: "Custom"
text_color: 0.3607, 0.3882, 1
#Custom buttons and text fields are located below
<PasswordField>:
size_hint_y: None
height: text_field.height
MDTextField:
id: text_field
hint_text: root.hint_text
text: root.text
password: True
icon_left: "lock"
MDIconButton:
icon: "eye-off"
pos_hint: {"center_y": .5}
pos: text_field.width - self.width + dp(8), 0
theme_text_color: "Hint"
on_release:
self.icon = "eye" if self.icon == "eye-off" else "eye-off"
text_field.password = False if text_field.password is True else True
<ConfirmPasswordField>:
size_hint_y: None
height: text_field.height
MDTextField:
id: text_field
hint_text: root.hint_text
text: root.text
password: True
icon_left: "lock"
MDIconButton:
icon: "eye-off"
pos_hint: {"center_y": .5}
pos: text_field.width - self.width + dp(8), 0
theme_text_color: "Hint"
on_release:
self.icon = "eye" if self.icon == "eye-off" else "eye-off"
text_field.password = False if text_field.password is True else True
<EmailField>:
size_hint_y: None
height: email_field.height
MDTextField:
id: email_field
hint_text: root.hint_text
text: root.text
icon_left: "email"
<NameField>:
size_hint_y: None
height: name_field.height
MDTextField:
id: name_field
hint_text: root.hint_text
text: root.text
icon_left: "account"
Below is the result:
Failed attempt (it does scroll but the layout is wrong)
Any help would be greatly appreciated, thanks!
A GridLayout is not required. Try using a BoxLayout, like this:
<SignupScreen>:
ScrollView:
BoxLayout:
orientation: 'vertical'
# cols: 1

How to change screens from python code in Kivy

So I'm working on making a fully functional login screen for my first serious kivy app and I want to be able to change windows/screens when the user presses on a button. I know normally in the KV file i'd just use on release but I want the on release to call to a method to verify the users credentials, and if those credentials are correct then change screens. So how in python itself would I be able to call to screen manager to change the screen?
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
class LoginLayout(Screen):
def login(self, **kwargs):
print("Login function working")
userEmail = self.ids.username.text
userPassword = self.ids.password.text
print(userEmail)
print(userPassword)
ScreenManager.current('emailWindow')
class EmailWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('loginScreen.kv')
class LoginScreen(App):
def build(self):
return kv
app = LoginScreen()
app.run()
KV
ScreenManager:
LoginLayout:
EmailWindow:
<LoginLayout>:
name: 'loginWindow'
canvas.before:
Color:
rgba: (28/255, 102/255, 137/255, 1)
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
size: root.width, root.height
Label:
text: 'Username'
font_name: 'Framd.ttf'
font_size: 20
TextInput:
id: username
multiline: False
size_hint: (.5, .3)
pos_hint: {'center_x' : .5}
Label:
text: 'Password'
font_name: 'Framd.ttf'
font_size: 20
TextInput:
id: password
multiline: False
size_hint: (.5, .3)
pos_hint: {'center_x' : .5}
Button:
text: 'Login'
size_hint: (.2, .8)
pos_hint: {'center_x' : 0.5}
font_name: 'Framd.ttf'
on_release: root.login()
Button:
text: 'Create Account'
size_hint: (.2, .8)
pos_hint: {'center_x' : 0.5}
font_name: 'Framd.ttf'
Button:
text: 'Forgot login Info'
size_hint: (.2, .8)
pos_hint: {'center_x' : 0.5}
font_name: 'Framd.ttf'
<EmailWindow>:
name: 'emailWindow'
canvas.before:
Color:
rgba: (28/255, 102/255, 137/255, 1)
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
size: root.width, root.height
Label:
text: 'To:'
font_name: 'Framd.ttf'
TextInput:
multiline: False
pos_hint: {'center_x': 0.5}
size_hint: (.5, .3)
font_name: 'Framd.ttf'
Label:
text: 'Subject'
TextInput:
multiline: False
pos_hint: {'center_x': 0.5}
size_hint: (.5, .3)
font_name: 'Framd.ttf'
Label:
text: 'Body'
font_name: 'Framd.ttf'
TextInput:
size_hint: (.5, .7)
pos_hint: {'center_x': 0.5}
multiline: True
Button:
text: 'send'
size_hint: (.2, .8)
pos_hint: {'center_x' : 0.5}
font_name: 'Framd.ttf'
When a Screen gets added to a ScreenManager, it gets a manager attribute set to the ScreenManager. So in your login() method you can do:
self.manager.current = 'emailWindow'
instead of:
ScreenManager.current('emailWindow')
Note that using ScreenManager, as you do above, references the ScreenManager class, not the ScreenManager instance that is in your App.

How to get user input from an MDTextField in KivyMD

Please I keep getting an attribute error when I try to get the text a user input into an MDTextField, tried everything I could think of, researched and couldn't get anything. Please I need your help.
I try to get the text with this argument of self.root.ids.MyId.text
This is the error I get:
File "C:/Users/user/Documents/KmD/Webma/main_webma.py", line 120, in login
email_addr = self.root.ids.email.text
File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__'
And this is my main.py code
from kivymd.app import MDApp
from kivy.clock import Clock
from kivy.lang import Builder
from home_page_strings import toolbar
import sqlite3
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.picker import MDThemePicker
from kivy.uix.popup import Popup
from kivymd.uix.textfield import MDTextField
# calling of screen classes and addition to the screen_manager
class Friend1(Screen):
pass
class WelcomeScreen(Screen):
def __init__(self, **kwargs):
super(WelcomeScreen, self).__init__(**kwargs)
Clock.schedule_once(self.callNext, 5)
def callNext(self, dt):
self.manager.current = 'account'
class AccountScreen(Screen):
pass
class HomeScreen(Screen):
pass
class RoomScreen(Screen):
pass
class ContactsScreen(Screen):
pass
class CallsScreen(Screen):
pass
class SettingsScreen(Screen):
pass
class FaqScreen(Screen):
pass
class InviteScreen(Screen):
pass
manager = ScreenManager()
manager.add_widget(Friend1(name='friend1'))
manager.add_widget(HomeScreen(name='home'))
manager.add_widget(WelcomeScreen(name='welcome'))
manager.add_widget(RoomScreen(name='room'))
manager.add_widget(ContactsScreen(name='contacts'))
manager.add_widget(CallsScreen(name='calls'))
manager.add_widget(SettingsScreen(name='settings'))
manager.add_widget(FaqScreen(name='faq'))
manager.add_widget(InviteScreen(name='invite'))
manager.add_widget(AccountScreen(name='account'))
# end of call of screen classes and addition to screenmanager
class EMC_WebmaApp(MDApp):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# -------------------------- CODE FOR THE DATABASE ---------------------------------- #
conn = sqlite3.connect('webma_database.db')
cursor = conn.cursor()
# cursor.execute('''CREATE TABLE users (
# email text,
# password integer
# )''')
def sign_up(self, cursor):
cursor.execute('INSERT INTO users VALUES('', '')')
conn.commit()
conn.close()
# -------------------------- END OF CODE FOR THE DATABASE ---------------------------------- #
# BUILDER FUNCTION AND SCREEN
def build(self):
screen = Screen()
# theme settings
self.theme_cls.primary_palette = 'DeepPurple'
self.theme_cls.theme_style = 'Dark'
# end of theme declaration
# loaded strings
navigation_bar = Builder.load_string(toolbar)
# end of loaded strings
# addition of loaded strings to screen + return screen
screen.add_widget(navigation_bar)
return screen
# end of addition
# END OF BUILDER FUNCTION
# USER VALIDATION FUNCTION
def login(self):
email_addr = self.root.ids.email.text
if email_addr == str(''):
print('Invalid Email Address')
# END OF USER VALIDATION
def change(self, dt):
self.root.manager.current = 'home'
# App theme manager
def change_theme(self):
picker = MDThemePicker()
picker.open()
# End of app theme manager
# home page search bar
def search_bar(self, dt):
searchbar = Popup(
title='Search',
content=MDTextField(
helper_text='Input values to be searched for',
helper_text_mode='on_focus'
),
auto_dismiss=True,
# size_hint=(None, None),
# size=(400, 98)
size_hint=(0.7, 0.17),
pos_hint={'center_x': 0.5, 'center_y': 0.8}
)
searchbar.open()
# APP RUN
if __name__ == '__main__':
EMC_WebmaApp().run()
# WELL... THIS IS THE END OF EVERYTHING
Then my string code where I try to get my text from
toolbar = '''
ScreenManager:
WelcomeScreen:
HomeScreen:
RoomScreen:
ContactsScreen
CallsScreen:
SettingsScreen:
FaqScreen:
InviteScreen:
AccountScreen:
Friend1:
<WelcomeScreen>:
name: 'welcome'
Image:
source: 'logo.png'
size_hint: 0.4, 0.4
pos_hint: {'center_x': 0.5, 'center_y':0.6}
MDLabel:
text: 'Webma'
halign: 'center'
font_style: 'H3'
color: (1, 1, 1, 1)
pos_hint: {'center_x': 0.5, 'center_y':0.8}
MDLabel:
text: 'Powered by emc_codes'
halign: 'center'
bold: 'True'
italic: True
pos_hint: {'center_x': 0.5, 'center_y':0.1}
<HomeScreen>:
name: 'home'
NavigationLayout:
ScreenManager:
Screen:
BoxLayout:
orientation: 'vertical'
spacing: '8dp'
MDToolbar:
title: 'EMC_Webma'
left_action_items: [['menu', lambda x: navigation.set_state('open')]]
right_action_items: [['card-search', app.search_bar]]
elevation: 10
ScrollView:
MDList:
TwoLineAvatarIconListItem:
text: 'Friend 1'
ImageLeftWidget:
source: 'einstein.jpg'
IconRightWidget:
icon: 'dots-vertical'
MDNavigationDrawer:
id: navigation
BoxLayout:
orientation: 'vertical'
spacing: '8dp'
padding: '8dp'
Image:
source: 'einstein.jpg'
MDLabel:
text: 'Enwerem Melvin Confidence'
font_style: 'Subtitle2'
size_hint_y: None
height: self.texture_size[1]
MDLabel:
text: 'enweremmelvinconfidence#gmail.com'
font_style: 'Caption'
size_hint_y: None
height: self.texture_size[1]
ScrollView:
MDList:
OneLineIconListItem:
text: 'Room'
on_release: root.manager.current = 'room'
IconLeftWidget:
icon: 'theater'
on_release: root.manager.current = 'room'
OneLineIconListItem:
text: 'Contacts'
on_release: root.manager.current = 'contacts'
IconLeftWidget:
icon: 'contacts'
on_release: root.manager.current = 'contacts'
OneLineIconListItem:
text: 'Calls'
on_release: root.manager.current = 'calls'
IconLeftWidget:
icon: 'cellphone-android'
on_release: root.manager.current = 'calls'
OneLineIconListItem:
text: 'Settings'
on_release: root.manager.current = 'settings'
IconLeftWidget:
icon: 'settings'
on_release: root.manager.current = 'settings'
OneLineIconListItem:
text: 'FAQ'
on_release: root.manager.current = 'faq'
IconLeftWidget:
icon: 'frequently-asked-questions'
on_release: root.manager.current = 'faq'
OneLineIconListItem:
text: 'Invite Friends'
on_release: root.manager.current = 'invite'
IconLeftWidget:
icon: 'account-plus'
on_release: root.manager.current = 'invite'
OneLineIconListItem:
text: 'Theme Manager'
on_release:
app.change_theme()
IconLeftWidget:
icon: 'theme-light-dark'
<RoomScreen>:
name: 'room'
MDLabel:
text: 'Welcome to the Room Screen'
halign: 'center'
bold: True
font_size: 50
MDIconButton:
icon: 'keyboard-backspace'
pos_hint: {'center_x': 0.06, 'center_y': 0.96}
on_release: root.manager.current = 'home'
size_hint: None, None
<ContactsScreen>:
name: 'contacts'
MDLabel:
text: 'Welcome to the Contacts Screen'
halign: 'center'
bold: True
font_size: 50
MDIconButton:
icon: 'keyboard-backspace'
pos_hint: {'center_x': 0.06, 'center_y': 0.96}
on_release: root.manager.current = 'home'
size_hint: None, None
<CallsScreen>:
name: 'calls'
MDLabel:
text: 'Welcome to the Calls Screen'
halign: 'center'
bold: True
font_size: 50
MDIconButton:
icon: 'keyboard-backspace'
pos_hint: {'center_x': 0.06, 'center_y': 0.96}
on_release: root.manager.current = 'home'
size_hint: None, None
<SettingsScreen>:
name: 'settings'
MDLabel:
text: 'Welcome to the Settings Screen'
halign: 'center'
bold: True
font_size: 50
MDIconButton:
icon: 'keyboard-backspace'
pos_hint: {'center_x': 0.06, 'center_y': 0.96}
on_release: root.manager.current = 'home'
size_hint: None, None
<FaqScreen>:
name: 'faq'
MDLabel:
text: 'Welcome to the Faq Screen'
halign: 'center'
bold: True
font_size: 50
MDIconButton:
icon: 'keyboard-backspace'
pos_hint: {'center_x': 0.06, 'center_y': 0.96}
on_release: root.manager.current = 'home'
size_hint: None, None
<InviteScreen>:
name: 'invite'
MDLabel:
text: 'Welcome to the Invite Screen'
halign: 'center'
bold: True
font_size: 50
MDIconButton:
icon: 'keyboard-backspace'
pos_hint: {'center_x': 0.06, 'center_y': 0.96}
on_release: root.manager.current = 'home'
size_hint: None, None
<AccountScreen>:
name: 'account'
BoxLayout:
MDLabel:
text: 'Account Login'
pos_hint: {'center_x': 0.6, 'center_y': 0.9}
color: (1, 1, 1, 1)
font_size: 40
MDTextFieldRound:
id: email
hint_text: 'Email Address'
icon_right: 'email'
icon_right_color: app.theme_cls.primary_color
pos_hint: {'center_x': 0.5, 'center_y': 0.7}
size_hint_x: None
width: 300
MDTextFieldRound:
id: password
hint_text: 'Enter Password'
icon_right: 'lock'
icon_right_color: app.theme_cls.primary_color
password: True
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
size_hint_x: None
width: 300
MDRaisedButton:
text: 'Login'
md_bg_color: app.theme_cls.primary_color
pos_hint: {'center_x': 0.5, 'center_y': 0.2}
on_release: app.login() # root.manager.current = 'home'
<Friend1>
name: 'friend1'
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: 'Friend 1'
left_action_items: [['keyboard-backspace', app.change]]
right_action_items: [['phone', lambda x: print('go ahead and make a call')], ['video', lambda x: print('Video')], ['dots-vertical', lambda x: print('dots')]]
MDLabel:
text: 'This is a test screen for our Chat'
halign: 'center'
'''
Please guys I really appreciate the help. Thanks in advance...
The email id only appears in the ids for the AccountScreen. Any id appearing in a kv gets inserted into the ids of the widget that is the root of the rule that contains the id. So, you must access the AccountScreen instance to get to the email id:
# BUILDER FUNCTION AND SCREEN
def build(self):
screen = Screen()
# theme settings
self.theme_cls.primary_palette = 'DeepPurple'
self.theme_cls.theme_style = 'Dark'
# end of theme declaration
# loaded strings
self.navigation_bar = Builder.load_string(toolbar) # save a reference to the loaded ScreenManager
# end of loaded strings
# addition of loaded strings to screen + return screen
screen.add_widget(self.navigation_bar)
return screen
# end of addition
# END OF BUILDER FUNCTION
# USER VALIDATION FUNCTION
def login(self):
# use the saved reference to access the email address
email_addr = self.navigation_bar.get_screen('account').ids.email.text
if email_addr == str(''):
print('Invalid Email Address')
# END OF USER VALIDATION
value = self.root.get_screen('nameofscreen').ids.username.text
print("What you typed is: ", value)
syntax = self.root.get_screen('name').ids.id.text

First Python/Kivy/KivyMD App. Unable to save data from textfield to variable + data binding to MDList

I recently started to work on a school turn in app in python/kivy.
I'm at the state where I created and UI in kivymd and a user class.
I want to save the info into a list of user objects but I get a KeyError: 'firstname' error message.
Do you guys know what can be the problem?
Also what I want to implement, is that I put a MDList to the second screen. With Data Binding I want to show the First and Last names of the users that are in the list. Any idea how can I achive that? I didn't find and usable solutions on the web.
Thank you for your help in advance!
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.textinput import _textinput_list
screen_helper = """
ScreenManager:
id: smn
AddUserScreen:
ViewListScreen:
ModifyUser:
<AddUserScreen>:
id: screen1
name: 'adduser'
MDTextField:
id:firstname
hint_text: "First Name"
helper_text: "Please enter your firts name"
helper_text_mode: "on_focus"
pos_hint: {'center_x': 0.5, 'center_y': 0.9}
size_hint_x: None
width:300
MDTextField:
id: lastname
hint_text: "Last Name"
helper_text: "Please enter your last name"
helper_text_mode: "on_focus"
pos_hint: {'center_x': 0.5, 'center_y': 0.8}
size_hint_x: None
width:300
MDTextField:
id: city
hint_text: "City of Residence"
helper_text: "Please enter your city of residence"
helper_text_mode: "on_focus"
pos_hint: {'center_x': 0.5, 'center_y': 0.7}
size_hint_x: None
width:300
MDTextField:
id: year
hint_text: "Birthyear"
helper_text: "Please enter your birthyear"
helper_text_mode: "on_focus"
pos_hint: {'center_x': 0.5, 'center_y': 0.6}
size_hint_x: None
width:300
MDRectangleFlatButton:
text: 'View User List'
pos_hint: {'center_x': 0.7, 'center_y': 0.1}
on_press: root.manager.current = 'viewlists'
MDRectangleFlatButton:
text: 'Add User'
pos_hint: {'center_x': 0.3, 'center_y': 0.1}
on_press: root.addUser()
<ViewListScreen>:
id: screen2
name: 'viewlists'
MDList:
id: container
pos_hint: {'center_x': 0.5, 'center_y': 0.9}
MDRectangleFlatButton:
text: 'Add New User'
pos_hint: {'center_x': 0.3, 'center_y': 0.1}
on_press: root.manager.current = 'adduser'
MDRectangleFlatButton:
text: 'Modify User'
pos_hint: {'center_x': 0.7, 'center_y': 0.1}
on_press: root.manager.current = 'modify'
<ModifyUser>:
id: 'screen3"
name: 'modify'
MDRectangleFlatButton:
text: 'Add New User'
pos_hint: {'center_x': 0.3, 'center_y': 0.1}
on_press: root.manager.current = 'adduser'
MDRectangleFlatButton:
text: 'View User'
pos_hint: {'center_x': 0.7, 'center_y': 0.1}
on_press: root.manager.current = 'viewlists'
"""
class AddUserScreen(Screen):
def addUser(self):
screen1_instance = sm.get_screen('adduser')
firstname1 = screen1_instance.ids['firstname'].text
lastname1 = screen1_instance.ids['lastname'].text
city1 = screen1_instance.ids['city'].text
year1 = screen1_instance.ids['year'].text
userlist.append(User(firstname1, lastname1, city1, year1))
print('New User Added')
class ViewListScreen(Screen):
pass
class ModifyUser(Screen):
pass
userlist = []
sm = ScreenManager()
sm.add_widget(AddUserScreen(name='adduser'))
sm.add_widget(ViewListScreen(name='viewlists'))
sm.add_widget(ModifyUser(name='modify'))
class App(MDApp):
def build(self):
screen = Builder.load_string(screen_helper)
return screen
App().run()
class User:
def __init__(self, firstname, lastname, country, year):
self.firstname = firstname
self.lastname = lastname
self.country = country
self.year = year
A few issues with your code. First, the lines:
sm = ScreenManager()
sm.add_widget(AddUserScreen(name='adduser'))
sm.add_widget(ViewListScreen(name='viewlists'))
sm.add_widget(ModifyUser(name='modify'))
are building a widget tree that is not used in your App. These lines can be removed.
Second, the User class definition appears after the App().run(), which means that the running App does not have that class available. This class definition should be moved before the App().run()
Third, the addUser() method uses the sm defined above, which is not part of your App widget tree, has not been displayed, and therefore, has no ids (causing the error). A correction to the addUser() method accesses the actual widget tree of the App. Like this:
class AddUserScreen(Screen):
def addUser(self):
screen1_instance = self.manager.get_screen('adduser') # get correct Screen
firstname1 = screen1_instance.ids['firstname'].text
lastname1 = screen1_instance.ids['lastname'].text
city1 = screen1_instance.ids['city'].text
year1 = screen1_instance.ids['year'].text
userlist.append(User(firstname1, lastname1, city1, year1))
print('New User Added')
Also, naming your App as App is probably a bad idea, as App is the name of the base class of MDApp. A better idea is to choose a name that is unique.

Categories