Class method does not run when called upon in Kivy - python-3.x

I am new to kivy.
I have created a login page with 2 text fields. I am now trying to pass the variables to the next page, which will use a ssh client for python to connect to a server. However, when I run the program, it seems that the method I am calling in my second screen does not even run, as none of the debugging output shows up.
I have tried a few methods of passing in variables into a function of a different class, and temporarily I have set upon using global variables. I am sure there is an easier or better way, but I can't get the function to run in the first place.
main.py
from kivy.config import Config
Config.set('graphics', 'resizable', False)
from kivy.app import App
from kivy.properties import StringProperty
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
import csv
import paramiko
#import os
global username
global password
def load_csv(filepath):
with open(filepath, newline='') as csvfile:
file_array = list(csv.reader(csvfile))
csvfile.close()
return file_array
class Connect(Screen):
Window.size = (600, 300)
def routine(self):
host = 'titanrobotics.ddns.net'
port = 60022
print(username, password)
self.ids.status.text = "connecting"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.ids.status.text = "attempting to connect to " + host
ssh.connect(host, port, username, password)
yield ssh
self.ids.status.text = "connected to " + host
finally:
ssh.close()
self.ids.status.text = "connection failed"
#print("here")
#ssh = loginroutine(username, password)
class Login(Screen):
Window.size = (600, 300)
def do_login(self, loginText, passwordText):
app = App.get_running_app()
username = loginText
password = passwordText
self.manager.transition = SlideTransition(direction = "left")
self.manager.current = "connect"
def resetForm(self):
self.ids['login'].text = ""
self.ids['password'].text = ""
class BrummetApp(App):
username = StringProperty(None)
password = StringProperty(None)
title = 'Brummet Client v ' + load_csv("data/meta")[0][1]
def build(self):
manager = ScreenManager()
manager.add_widget(Login(name = 'login'))
manager.add_widget(Connect(name = 'connect'))
return manager
if __name__ == '__main__':
BrummetApp().run()
brummet.kv
<Login>:
BoxLayout
id: login_layout
orientation: 'vertical'
padding: [10,10,10,10]
spacing: 10
BoxLayout:
orientation:'vertical'
padding: [0,0,0,0]
spacing: 0
Label:
id: title
text: 'Brummet Client'
halign: 'center'
valign: 'middle'
font_size: 24
Label:
text: 'Please log in with IMSA SLURM credentials'
halign: 'center'
valign: 'middle'
spacing: -20
font_size: 24
BoxLayout:
orientation: 'vertical'
Label:
text: 'Username'
font_size: 18
halign: 'left'
text_size: root.width-20, 0
TextInput:
id: username
multiline: False
font_size: 16
write_tab: False
BoxLayout:
orientation: 'vertical'
Label:
text: 'Password'
halign: 'left'
font_size: 18
text_size: root.width-20, 0
TextInput:
id: password
multiline: False
password: True
font_size: 16
write_tab: False
Button:
text: 'Log In'
font_size: 24
on_press:
root.do_login(username.text, password.text)
<Connect>:
on_enter:
root.routine()
BoxLayout:
orientation: 'vertical'
padding: [0,125,0,125]
spacing: 0
Label:
text:'Logging In'
font_size: 24
halign: 'center'
valign: 'middle'
Label:
id: status
test:''
font_size: 16
halign: 'center'
valign: 'middle'
It seems that loading the Connect class is fine, however I am unable to run the .routine() method on_enter.

The yield ssh is preventing the Connect.routine() from executing. Try comment it off.

Related

pyrebase auth and kivy signup and login pages

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

KivyMD on changing screen not creating MDList Items widget using root.ids and showing error

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)

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")

Changing screens from a Spinner on_text problem

I'm wanting to create a type of workflow using ScreenManager that progresses as options are selected. I have several screens defined within ScreenManager and within one screen I have created a Spinner with several options. I'm wanting to call a Function from the on_text and pass the selected Spinner value, perform a task based on the passed value and then move to the next screen in the workflow.
I've created a Function inside a class (Screen) with only a print() for testing purposes. When I select an option from the Spinner nothing happens.
I've only provided what I think is the relevant code...
kv file:
<HomeScreen>:
name: 'homeScreen'
BoxLayout:
orientation: 'horizontal'
Label:
id: 'home'
text: 'Home Screen'
<NewSession>:
name: 'newSession'
BoxLayout:
orientation: 'vertical'
Label:
id: new
text: 'Create New Session'
Spinner:
size_hint: None, None
size: 100, 25
id: category
font_size: 12
text: "Food Category" #default value showed
values: ["Beef","Pork","Poultry", "Fish"] #list of values to show
on_text: root.SelectCut(category.text)
Widget:
<CurrentSession>:
id: cs
name: 'currentSession'
BoxLayout:
orientation: 'vertical'
Label:
id: cSession
text: root.cSession
<History>:
name: 'history'
BoxLayout:
orientation: 'vertical'
Label:
id: 'history'
text: 'History Data Screen'
<ScreenManagement>:
HomeScreen:
NewSession:
CurrentSession:
History:
<AllScreen>:
orientation: 'vertical'
ScreenManagement:
id: sm
BoxLayout:
size_hint_y: None
height: 60
spacing: 5
padding: 5, 5, 0, 5
Button:
text: 'Home'
on_press: root.ids.sm.current = 'homeScreen'
Button:
text: 'New Session'
on_press: root.ids.sm.current = 'newSession'
Button:
text: 'Current Session'
on_press:
root.ids.sm.current = 'currentSession'
Button:
text: 'History'
on_press: root.ids.sm.current = 'history'
py file:
Builder.load_file("screenLayout.kv")
class ScreenManagement(ScreenManager):
pass
class HomeScreen(Screen):
pass
class NewSession(Screen):
def SelectCut(self, text):
print("In Select Cut")
print("Food Category: " + text)
self.sm.current = 'homeScreen'
class CurrentSession(Screen):
pass
class History(Screen):
pass
class AllScreen(BoxLayout):
pass
class WorkingTestApp(App):
def build(self):
self.root = AllScreen()
return self.root
if __name__ == '__main__':
WorkingTestApp().run()
I'm not able to figure out why nothing is happening when a selection is made from the Spinner and I'm not sure what the syntax will be from within the Function to move to the next screen.
Update:
Current code (minus imports)
kv:
<HomeScreen>:
name: 'homeScreen'
BoxLayout:
orientation: 'horizontal'
Label:
id: 'home'
text: 'Home Screen'
<NewSession>:
name: 'newSession'
BoxLayout:
orientation: 'vertical'
Label:
id: new
text: 'Create New Session'
Spinner:
size_hint: None, None
size: 100, 25
id: category
font_size: 12
text: "Food Category" #default value showed
values: ["Beef","Pork","Poultry", "Fish"] #list of values to show
on_text: root.SelectCategory()
Widget:
<SelectCut>:
name: 'selectCut'
BoxLayout:
orientation: 'vertical'
Label:
id: 'cut'
text: 'Select Cut Screen'
Widget:
<CurrentSession>:
name: 'currentSession'
BoxLayout:
orientation: 'vertical'
Label:
id: cSession
text: 'Current Session Screen'
<History>:
name: 'history'
BoxLayout:
orientation: 'vertical'
Label:
id: 'history'
text: 'History Data Screen'
<ScreenManagement>:
HomeScreen:
NewSession:
SelectCut:
CurrentSession:
History:
<AllScreen>:
orientation: 'vertical'
ScreenManagement:
id: sm
BoxLayout:
size_hint_y: None
height: 60
spacing: 5
padding: 5, 5, 0, 5
Button:
text: 'Home'
on_press: root.ids.sm.current = 'homeScreen'
Button:
text: 'New Session'
on_press: root.ids.sm.current = 'newSession'
Button:
text: 'Current Session'
on_press:
root.ids.sm.current = 'currentSession'
Button:
text: 'History'
on_press: root.ids.sm.current = 'history'
py:
Builder.load_file("screenLayout.kv")
class ScreenManagement(ScreenManager):
pass
class HomeScreen(Screen):
pass
class NewSession(Screen):
# This Function isn't executing consistently.
def SelectCategory(self):
print("Food Category: " + self.ids.category.text)
self.manager.current = 'selectCut'
class SelectCut(Screen):
pass
class CurrentSession(Screen):
pass
class History(Screen):
pass
class AllScreen(BoxLayout):
pass
class WorkingTestApp(App):
def build(self):
self.root = AllScreen()
return self.root
if __name__ == '__main__':
WorkingTestApp().run()
change your spinner's on_text: root.SelectCut(self, text) to on_text: root.SelectCut() the in your .py change def SelectCut(self, text): to def SelectCut(self): then to change the text you can use self.ids.category.text to read or alter the spinner's text and add root.ids.sm.current = 'your screen' to this function as well

How to change text of label in a screen when I press a button in another screen in Kivy

I am new to Kivy, so I have a question that I want to develop two screen in Kivy, the first one is about entering user details and passwords (no authentication, at this moment) and then second screen displays the user name (entered at the previous screen) and displays user name along with other widgets.
The basic idea is to get the value of a user form userlogin screen and display it to another screen.
Here is my code,
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty # #UnresolvedImport
class LoginScreen(Screen):
text = StringProperty()
def change_text(self):
self.text = ''
self.manager.current = 'StocksGUIScreen'
class StocksGUIScreen(Screen):
label_text = StringProperty('')
#pass
class PortfolioUIApp(App):
#user_name = StringProperty()
pass
PortfolioUIApp().run()
Here is my .kv file:
ScreenManager:
id: screen_manager
LoginScreen:
id: login_screen
name: 'LoginScreen'
manager: screen_manager
StocksGUIScreen:
id: stocks_gui
name: 'StocksGUIScreen'
manager: screen_manager
label_text: login_screen.text
<LoginScreen>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
Label:
text: "User Name"
size_hint: 0.3,0.2
#pos: root.x, root.top-self.height
color: 0,1,0,1
TextInput:
id: user_name
size_hint: 0.3,0.2
#on_text: root.user_name
BoxLayout:
Label:
text: "Password"
size_hint: 0.3,0.2
TextInput:
id: pass_word
password: True
size_hint: 0.3,0.2
BoxLayout:
Button:
text: 'Log In'
size_hint: 0.3,0.2
on_press:
#root.manager.current = 'StocksGUIScreen'
root.label_text: user_name
root.change_text()
Button:
text: 'Cancel'
size_hint: 0.3,0.2
on_release: app.stop()
<StocksGUIScreen>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'horizontal'
TextInput:
size_hint_x: 50
id: ticker_search
Button:
text: "Go"
size_hint_x: 25
on_press: root.search_stock()
id: search_box
Label:
text: root.label_text
size_hint_x: 25
BoxLayout:
height: "10dp"
size_hint_y: 5
Label:
size_hint_x: .2
size_hint_y: .1
text: "Advice"
color: [1,0,0,1]
text_size: self.size
halign: 'left'
valign: 'top'
ScrollView:
size: self.size
GridLayout:
id: layout_content
size_hint_y: None
cols: 1
row_default_height: '20dp'
row_force_default: True
spacing: 0, 0
padding: 0, 0
color: [1,0,0,1]
Label:
text: "Lorem ipsum dolor sit amet"*10
id: advice_message
text_size: self.size
halign: 'left'
valign: 'top'
BoxLayout:
height: "10dp"
size_hint_y: 10
Label:
size_hint_x: .2
size_hint_y: .1
text: "Graphical Stuff"
id: graphical_stuff
text_size: self.size
halign: 'left'
valign: 'top'
AsyncImage:
source: "abc.png"
id: graphical_stuff
allow_stretch: True
keep_ratio: False
pos: 200,300
size: root.width*0.5,root.height*0.2
BoxLayout:
orientation: 'horizontal'
Button:
text: 'My settings button'
Button:
text: 'Back to Log in screen'
on_press: root.manager.current = 'LoginScreen'
What is wrong in this code, any help/guidance would be highly appreciated plz
If you want this setup, you can set an attribute on the first screen. Access it by id in your second screen.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivy.properties import StringProperty
class Screen1(Screen):
username = StringProperty("")
class Screen2(Screen):
username = StringProperty("")
root = Builder.load_string('''
<Screen1>:
BoxLayout:
orientation: "vertical"
TextInput:
id: username
Button:
text: "Login"
on_release: root.username = username.text; root.manager.current = "screen2"
<Screen2>:
name: "screen2"
Label:
text: root.username
ScreenManager:
Screen1:
id: loginscreen
Screen2:
username: loginscreen.username
''')
class MyApp(App):
def build(self):
return root

Resources