I'm trying to use the id function to reference text_input from MDTextField, however I can't understand how does the id function works. Does anyone know what is wrong in my code?
The first code is the Main App and the second one is where all the widgets are. I've already searched for a solution in internet, but I can't understand why my code does not work.
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from Screen_helper import Home
class MenuScreen(Screen):
pass
class ProfileScreen(Screen):
pass
sm = ScreenManager()
sm.add_widget(MenuScreen(name='Menu'))
sm.add_widget(MenuScreen(name='Profile'))
class Mainapp(MDApp):
def build(self):
screen = Screen()
helper = Builder.load_string(Home)
screen.add_widget(helper)
key = self.root.ids.username_input
return screen
Mainapp().run()
Home = '''
ScreenManager:
MenuScreen:
ProfileScreen:
<MenuScreen>:
name: 'Menu'
MDRectangleFlatButton:
id: my_button
text: 'Profile'
pos_hint: {'center_x': 0.5, 'center_y': 0.1}
on_press: root.manager.current = 'Profile'
MDTextField:
id: username_input
input_filter: "int"
hint_text: 'CHIAVE NUMERICA'
helper_text: 'compresa tra 0 e 95'
helper_text_mode: 'on_focus'
icon_right: 'key-variant'
icon_right_color: app.theme_cls.primary_color
pos_hint: {'center_x':0.5,'center_y':0.55}
size_hint_x:None
width:230
input_filter: 'int'
<ProfileScreen>:
name: 'Profile'
MDLabel:
text: 'Welcome'
halign: 'center'
MDRectangleFlatButton:
text: 'back'
pos_hint: {'center_x': 0.5, 'center_y': 0.3}
on_press: root.manager.current = 'Menu' '''
Give an id to the MenuScreen class and then access to the widget.
Add this to the kv file.
<MenuScreen>:
id: menu
To access the widget you can now do this in python:
key = self.root.menu.ids.username_input
Related
I want to know the method of loading the second screen when authentication is passed.
I can call the second screen from the .kv file vi on_press or other methods. But I need to call from python code to check the authentication.
Can anyone help with my code?
Here is my code:
app.py
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.properties import ObjectProperty
class my_layout(FloatLayout):
screen_mngr = ObjectProperty(None)
class myapp(MDApp):
def build(self):
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_palette = "BlueGray"
return Builder.load_file("app.kv")
def logger(self):
if self.root.ids.user.text == 'admin' and self.root.ids.password.text=='admin':
self.root.ids.welcome_label.text = f'Sup {self.root.ids.user.text}!'
screen = Screen(name='screen2')
else:
self.root.ids.welcome_label.text = 'Wrong credentials'
if __name__ == "__main__":
myapp().run()
And here is my design kv file.
app.kv file:
my_layout:
screen_mngr: screen_mngr
ScreenManager:
id: screen_mngr
home: home
Screen:
id: home
name: 'home'
MDCard:
size_hint: None, None
size: 450, 600
pos_hint: {"center_x": 0.5, "center_y": 0.5}
elevation: 10
padding: 25
spacing: 25
orientation: 'vertical'
MDLabel:
id: welcome_label
text: "WELCOME"
font_size: 40
halign: 'center'
size_hint_y: None
height: self.texture_size[1]
padding_y: 15
MDTextField:
id: user
hint_text: "username"
icon_right: "account"
size_hint_x: None
width: 200
font_size: 18
pos_hint: {"center_x": 0.5}
MDTextField:
id: password
hint_text: "password"
icon_right: "eye-off"
size_hint_x: None
width: 200
font_size: 18
pos_hint: {"center_x": 0.5}
MDRoundFlatButton:
text: "LOG IN"
font_size: 12
pos_hint: {"center_x": 0.5}
on_press: screen2
Screen:
id: screen2
name: 'screen2'
MDRoundFlatButton:
text: "This is Second Screen\nGo to Screen1"
size_hint: 0.2,0.1
pos_hint: {"center_x":0.5,"y":0.5}
on_press: screen_mngr.current = "home"
A couple small problems:
First, in your kv you need to have your LOG IN Button call the code to handle the log in, like this:
MDRoundFlatButton:
text: "LOG IN"
font_size: 12
pos_hint: {"center_x": 0.5}
on_press: app.logger() # call the method that handles login
Then, in that method, you can change to the screen2 by using the current property of the ScreenManager, like this:
def logger(self):
if self.root.ids.user.text == 'admin' and self.root.ids.password.text=='admin':
self.root.ids.welcome_label.text = f'Sup {self.root.ids.user.text}!'
self.root.ids.screen_mngr.current = 'screen2' # go to screen2
# screen = Screen(name='screen2')
else:
self.root.ids.welcome_label.text = 'Wrong credentials'
I wrote this code but now i don't know how to manipulate my images so I am stuck i need help on how to
add images if i have multiple screens
and how to also add other labels so basically screen manipulation with multiple screens
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
screen_helper = """
ScreenManager:
MenuScreen:
ProfileScreen:
<MenuScreen>:
name: "menu"
MDRectangleFlatButton:
text: 'Profile'
pos_hint: {'center_x':0.5, 'center_y':0.5}
on_press: root.manager.current = 'profile'
<ProfileScreen>:
name: 'profile'
MDLabel:
text: 'Welcome Nate'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5, 'center_y':0.2}
on_press: root.manager.current = 'menu'
"""
class MenuScreen(Screen):
pass
class ProfileScreen(Screen):
pass
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ProfileScreen(name='profile'))
class DemoApp(MDApp):
def build(self):
screen = Builder.load_string(screen_helper)
return screen
DemoApp().run()
You can use Image to put image
<ProfileScreen>:
name: 'profile'
Image:
source: '/home/furas/test/lenna.png'
MDLabel:
text: 'Welcome Nate'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5, 'center_y':0.2}
on_press: root.manager.current = 'menu'
Result:
Original image from Wikipedia: Lenna
EDIT:
Full code
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
screen_helper = """
ScreenManager:
MenuScreen:
ProfileScreen:
<MenuScreen>:
name: "menu"
Image:
source: '/home/furas/test/lenna.png'
MDRectangleFlatButton:
text: 'Profile'
pos_hint: {'center_x':0.5, 'center_y':0.5}
on_press: root.manager.current = 'profile'
<ProfileScreen>:
name: 'profile'
Image:
source: '/home/furas/test/lenna.png'
MDLabel:
text: 'Welcome Nate'
halign: 'center'
color: (0, 0, 0)
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5, 'center_y':0.2}
on_press: root.manager.current = 'menu'
"""
class MenuScreen(Screen):
pass
class ProfileScreen(Screen):
pass
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ProfileScreen(name='profile'))
class DemoApp(MDApp):
def build(self):
screen = Builder.load_string(screen_helper)
return screen
DemoApp().run()
I'm working on a project using Kivy with ScreenManager (and KivyMD).
The reason for using this is my need of making an application with multiple screens. My goal is to get User Input from an existing MDTextField by (a string) ID and then Print it out.
However, I keep getting this Error: File "<string>", line 37, in <module> File "c:/Users/admin/Desktop/myApp/Main.py", line 75, in loginFunction username = mainScreenInstance.ids["input_username"].text KeyError: 'input_username'.
I have searched for answers all over the internet and StackOverflow, but no solution seems to work for me. Maybe there's someone who can help me with my problem and make my code work.
Anyway, here's my short & simple Code:
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
import sys
screen_helper = """
ScreenManager:
MenuScreen:
name: 'menu'
SecondScreen:
name: 'second'
<MenuScreen>:
MDToolbar:
title: "Menu Screen"
pos_hint: {"top": 1}
anchor_title: "center"
md_bg_color: (0/255, 0/255, 0/255, 1)
Image:
source: "Logo_h_black.png"
pos_hint: {"center_x": 0.5, "center_y": 0.75}
size_hint_x: (0.25)
size_hint_y: (0.25)
MDTextField:
id: input_username
hint_text: "Username"
size_hint: (0.5, 0.1)
pos_hint: {"center_x": 0.5, "center_y": 0.55}
font_size: 20
mode: "rectangle"
MDTextField:
id: input_password
hint_text: "Password"
size_hint: (0.5, 0.1)
pos_hint: {"center_x": 0.5, "center_y": 0.45}
font_size: 20
mode: "rectangle"
MDFillRoundFlatButton:
text: "LOG IN"
font_size: 17
pos_hint: {"center_x": 0.5, "center_y": 0.25}
on_press: app.loginFunction()
<SecondScreen>:
MDLabel:
text: 'Profile'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.1}
on_press: root.manager.current = 'menu'
"""
class MenuScreen(Screen):
pass
class SecondScreen(Screen):
pass
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SecondScreen(name='second'))
class myApp(MDApp):
def loginFunction(self, args=None):
if args is None:
args = sys.argv
mainScreenInstance = sm.get_screen('menu')
username = mainScreenInstance.ids["input_username"].text
password = mainScreenInstance.ids["input_password"].text
print (username)
print (password)
def build(self):
screen = Builder.load_string(screen_helper)
return screen
myApp().run()
The problem is that your loginFunction is trying to get the mainScreenInstance from sm, but sm is created before the screen_helper is loaded, so it doesn't know about the ids you have defined in your screen_helper. Also, that sm is not actually used as part of you GUI, it is just ignored (except for your reference to it in the loginFunction).
So, I recommend that you eliminate the following lines completely:
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SecondScreen(name='second'))
And change loginFunction to not use sm by replacing:
mainScreenInstance = sm.get_screen('menu')
with:
mainScreenInstance = self.root.get_screen('menu')
You're duplicating the widget definitions and then not using them in code. Finally, you're overwriting the Screen manager from the screen_helper string with a new instance. Tbh I did some of that when I started learning Kivy. The kv language is confusing at first but once you get it is beautiful. This version should work (I haven't tested it since I haven't found an easy way to install kivymd on my phone's dev env):
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen
import sys
screen_helper = """
ScreenManager:
MenuScreen:
name: 'menu'
SecondScreen:
name: 'second'
<MenuScreen>:
MDToolbar:
title: "Menu Screen"
pos_hint: {"top": 1}
anchor_title: "center"
md_bg_color: (0, 0, 0, 1)
Image:
source: "Logo_h_black.png"
pos_hint: {"center_x": 0.5, "center_y": 0.75}
size_hint_x: (0.25)
size_hint_y: (0.25)
MDTextField:
id: input_username
hint_text: "Username"
size_hint: (0.5, 0.1)
pos_hint: {"center_x": 0.5, "center_y": 0.55}
font_size: 20
mode: "rectangle"
MDTextField:
id: input_password
hint_text: "Password"
size_hint: (0.5, 0.1)
pos_hint: {"center_x": 0.5, "center_y": 0.45}
font_size: 20
mode: "rectangle"
MDFillRoundFlatButton:
text: "LOG IN"
font_size: 17
pos_hint: {"center_x": 0.5, "center_y": 0.25}
on_press: app.loginFunction()
<SecondScreen>:
MDLabel:
text: 'Profile'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.1}
on_press: root.manager.current = 'menu'
"""
class MenuScreen(Screen):
pass
class SecondScreen(Screen):
pass
class myApp(MDApp):
sm = None
def on_start():
self.sm = self.root
def loginFunction(self, args=None):
if args is None:
args = sys.argv
mainScreenInstance = self.sm.get_screen('menu')
username = mainScreenInstance.ids["input_username"].text
password = mainScreenInstance.ids["input_password"].text
print (username)
print (password)
# if self.is_login_correct(username, password):
# self.sm.current('second')
def build(self):
return Builder.load_string(screen_helper)
myApp().run()
Personally, I would move all login-related functions to the MenuScreen class, for consistency.
I want to change the screen by pressing the button and checking that the text box is not empty.
here is my kv file:
test.kv:
ScreenManager:
id: sc_m
Screen:
name: 'welcome'
MDLabel:
text: 'WeLCOME'
halign: 'center'
font_style: 'H3'
color: (1, 1, 1, 1)
pos_hint: {'center_x': 0.5, 'center_y':0.8}
MDTextField:
id: textbox
hint_text: "The text box should not be empty"
text:""
pos_hint: {'center_x': .5, 'center_y': .5}
MDRoundFlatIconButton:
text: "OK"
icon: "folder"
pos_hint: {'center_x': .5, 'center_y': .3}
on_press: app.callback()
Screen:
name:'screen2'
MDLabel:
text: 'WeLCOME'
halign: 'center'
font_style: 'H3'
color: (1, 1, 1, 1)
pos_hint: {'center_x': 0.5, 'center_y':0.8}
and here is my python code:
main.py:
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
class MainApp(MDApp):
def build(self):
self.theme_cls.theme_style="Dark"
self.theme_cls.primary_palette="Cyan"
return Builder.load_file('test.kv')
def callback(self):
text = self.root.ids.textbox.text
if len(text)==0:
print('The text box should not be empty')
else:
self.root.ids.sc_m.current='screen2'
MainApp().run()
And the error i have:
error:
AttributeError: 'super' object has no attribute '__getattr__'
please help me!
Please do not read the rest of the article
I do not know what to say anymore because it gets an error when posting!
'''It looks like your post is mostly code; please add some more details.'''
Your code:
self.root.ids.sc_m.current='screen2'
is trying to use an id that does not exist. You cannot make an ids entry for the root object of a rule (the ids only includes lower level widgets). But, since the ScreenManager is the root widget, you don't need to access it using ids anyway. Just replace the above code with:
self.root.current = 'screen2'
I was trying to use a new feature in KivyMD, the MDNavigationRail and wanted to give the icons in it a function. The goal is that the user could change to the desired screen by pressing the icon that represents it. I gave the icon an on_press. But something goes wrong, I get an error; ValueError: MDNavigationRail.state is set to an invalid option 'down'. Must be one of: ['close', 'open']. The rail should be open or closed I guess, isn't it possible to give it a function? Furthermore, I would want to know if it is possible to not break the text. If anyone could help me out, it would be very nice!
My .py file
from kivy.uix.screenmanager import ScreenManager
from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
class Screen1(MDScreen):
def screen2(self):
self.manager.current = 'screen2'
class Screen2(MDScreen):
def screen1(self):
self.manager.current = 'screen1'
def rail_open(self):
if self.ids.rail.state == "open":
self.ids.rail.state = "close"
else:
self.ids.rail.state = "open"
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
class Test(MDApp):
def build(self):
return MyScreenManager()
Test().run()
My kv file
<MyScreenManager>:
Screen1:
id: screen1
name: 'screen1'
Screen2:
id: screen2
name: 'screen2'
<Screen1>:
id: screen1
MDFloatLayout:
MDRectangleFlatButton:
text: "Change to screen 2"
on_press: root.screen2()
pos_hint: {'center_x':0.5, 'center_y':0.5}
<Screen2>:
id: screen2
MDBoxLayout:
orientation: "vertical"
MDToolbar:
left_action_items: [["menu", lambda x: root.rail_open()]]
MDBoxLayout:
MDNavigationRail:
id: rail
elevation: 1
use_resizeable: True
MDNavigationRailItem:
icon: "home"
text: "homepage"
on_press: root.screen1()
MDNavigationRailItem:
icon: ""
text: ""
MDFloatLayout:
MDTextField:
id: field1
hint_text: "Enter something:"
size_hint_x: 0.4
pos_hint: {'center_x':0.25,'top':0.8}
It was a bug. Already fixed - https://github.com/kivymd/KivyMD/commit/8a31b0f3ccad9c2d9ad35d80953f7396f2dc78f2