How to bind MDTextField input with Label's text on second screen - python

I have started creating small app and I'm stuck. I tried many different ideas from this forum but nothing fit my app. I'm already confused how should I do this.
All I want is to take the input from MDTextField (which is provided by user) and show it in the Label's text on the Second Screen.
My .kv file:
ScreenManager:
First:
Second:
<First#Screen>:
name: 'screen1'
MDTextFieldRound:
id: getpath
text: "Enter player name"
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
size_hint_x: None
width: 300
mode: "rectangle"
icon_right: "scissors-cutting"
MDRectangleFlatButton:
text: "Submit"
pos_hint: {'center_x': .5, 'center_y': 0.4}
on_release: root.manager.current = 'screen2'
<Second#Screen>:
name: 'screen2'
canvas:
Rectangle:
source: 'image.jpg'
pos: self.pos
size: self.size
Label:
id: lab
text: ''
My main.py:
class PKNApp(MDApp):
def build(self):
pass
PKNApp().run()

If you add an id for First Screen in your kv, like this:
ScreenManager:
First:
id: first
Second:
Then you can use that id to access the TextInput, like this:
Label:
id: lab
text: root.manager.ids.first.ids.getpath.text

Related

Python Kivy Dyanmic Class not defined

I keep getting a Name Error reporting "name TripButton is not defined" although I have a button called TripButton defined in the same .kv file.
#:kivy 1.11.1
<TripButton#Button>:
size_hint: (0.15,0.15)
pos_hint: {'y':0.84}
text:"Test Text"
<MyPopup>:
size_hint: 0.5, 0.5
auto_dismiss: False
title: 'New Trip'
BoxLayout:
orientation: 'vertical'
TextInput:
id: trip_name
multiline: False
BoxLayout:
size_hint_y: None
height: 30
Button:
text: 'Submit'
on_release:
root.parent.parent.add_widget(TripButton(text=trip_name.text, size_hint=(1,0.1)))
root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
<FirstScreen>:
name: 'first'
FloatLayout:
BoxLayout:
size_hint: (0.95, 0.95)
pos_hint: {'center_x':0.5, 'center_y':0.5}
orientation: "vertical"
canvas.before:
Color:
rgba: (1, 0, 0, 1) # Red color
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
TripButton:
Button:
text: 'Add Trip'
font_size: 12
size_hint: (0.1, 0.1)
pos_hint: {'right':1, 'bottom':1}
on_release: app.open_popup()
pos_hint: {'right':1, 'bottom':1}
on_release: app.open_popup()
I tried declaring the TripButton class above and below the MyPopup class and that didn't work. I compared my code with the kivy documentation for dynamic classes and the from what I can tell I'm matching the syntax. I tried importing the Button class in both the python file and the .kv file and that hasn't worked.
To clarify all of this is in the same .kv file in the same directory as the python file. the app runs until I click the submit button in MyPopup then the program crashes and I get the NameError. This is what I have in my python file.
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
class FirstScreen(Screen):
pass
class MyPopup(Popup):
pass
class MyApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(FirstScreen(name='first'))
sm.current = 'first'
return sm
def open_popup(self):
p = MyPopup()
p.open()
def add_button(self):
pass
if __name__ == '__main__':
MyApp().run()
What am I doing wrong? What else I can try? Thanks for your time.
To access classes defined within kv file use kivy.factory.Factory
Add id attribute to your button's BoxLayout, so replace following part of kv file:
BoxLayout:
TripButton:
with
BoxLayout:
id: trip_buttons
TripButton:
then replace:
root.parent.parent.add_widget(TripButton(text=trip_name.text, size_hint=(1,0.1)))
with:
app.root.current_screen.ids.trip_buttons.add_widget(kivy.factory.Factory.TripButton(text=trip_name.text, size_hint=(1,0.1)))
You also duplicated following lines within last button definition on first screen. Replace:
pos_hint: {'right':1, 'bottom':1}
on_release: app.open_popup()
pos_hint: {'right':1, 'bottom':1}
on_release: app.open_popup()
with
pos_hint: {'right':1, 'bottom':1}
on_release: app.open_popup()

How to add multiple textfield in kivymd

i am making a form screen in which a user can input data and upload it to database. I want them to be able to add multiple textfields on a button press if they still want to add something. it should be scrollable since the amount of textfields is based on how many the user really wants. i have this code right here but it doesn't really do what i had in mind.
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.tab import MDTabsBase
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.textfield import MDTextField
class TextField(MDTextField):
pass
class Tab(MDFloatLayout, MDTabsBase):
pass
class FormScreen(Screen):
pass
class DemoApp(MDApp):
#function to add text field
def add_textfield(self):
self.help.get_screen('form').ids.box.add_widget(
TextField(hint_text= 'adsf',
))
def upload(self):
name = self.help.get_screen('form').ids.input_1.text
def build(self):
self.help = Builder.load_file('form.kv')
# screen.add_widget(self.help)
return self.help
Here is my kv file:
ScreenManager:
FormScreen:
<FormScreen>
name: 'form'
MDBoxLayout:
orientation: "vertical"
MDToolbar:
# md_bg_color:app.dark2
title: "Upload Data"
type_height: "small"
left_action_items: [["arrow-left", lambda x : app.swtchScreen('collections')]]
right_action_items: [["eraser", lambda x : root.eraser()],["plus", lambda x : app.add_textfield()]]
MDTabs:
id: tabs
background_color: rgba(0,0,0,0)
tab_hint_x: True
Tab:
title: "Passport Data"
MDTextField:
id: input_1
hint_text: "Name"
pos_hint: {"center_x": 0.5, "center_y": 0.95}
size_hint: .75,0.09
color_mode: 'accent'
mode: "rectangle"
#additional textfieldss
MDTextField:
id: box
Thank you
You can modify the Tab to customize the layout you need to hold all necessary fields as follows,
MDTabs:
id: tabs
background_color: rgba(0,0,0,0)
tab_hint_x: True
Tab:
title: "Passport Data"
MDBoxLayout: # Add main container.
orientation: "vertical"
padding: dp(10)
spacing: dp(5)
MDTextField:
id: input_1
hint_text: "Name"
# pos_hint: {"center_x": 0.5, "center_y": 0.95}
# size_hint: .75,0.09 # "size_hint_y" will be set automatically.
pos_hint: {"center_x": 0.5}
size_hint_x: .75
color_mode: 'accent'
mode: "rectangle"
#additional textfields
ScrollView:
MDBoxLayout: # Add all text fields in this container.
id: box
orientation: "vertical"
adaptive_height: True # Grow vertically.
Alternatively you could've inherited Tab from MDBoxLayout,
class Tab(MDBoxLayout, MDTabsBase):
pass
Then the kvlang would be,
MDTabs:
id: tabs
background_color: rgba(0,0,0,0)
tab_hint_x: True
Tab:
title: "Passport Data"
orientation: "vertical"
padding: dp(10)
spacing: dp(5)
MDTextField:
id: input_1
hint_text: "Name"
# pos_hint: {"center_x": 0.5, "center_y": 0.95}
# size_hint: .75,0.09 # "y" will be set automatically.
pos_hint: {"center_x": 0.5}
size_hint_x: .75
color_mode: 'accent'
mode: "rectangle"
#additional textfieldss
ScrollView:
MDBoxLayout: # Add all text field here.
id: box
orientation: "vertical"
adaptive_height: True # Grow vertically.

Kivy - Get InputText From Other Screen

I am trying to type in text from one screen. Press a button and move to another screen and have that text be shown in a label. I've seen a few questions that are similar to mine, but have not been able to figure out how to use the posted solutions and have been stuck for hours (Link One, Link Two, Link Three). I believe that I need to use the __init__ method somewhere because this is an instance? I tried using the first link, but the label ends up blank (the code does run). Any Advice?
main.py
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.app import App
from kivy.lang.builder import Builder
class SecondWindow(Screen):
def get_unique_text(self):
x = self.manager.get_screen("first")
y = x.ids.unique.text
return str(y)
class FirstWindow(Screen):
pass
class MainWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv_main = Builder.load_file('main.kv')
class MyApp(App):
def build(self):
return kv_main
if __name__ == '__main__':
MyApp().run()
main.kv
#:include First.kv
#:include Second.kv
WindowManager:
MainWindow:
FirstWindow:
SecondWindow:
<MainWindow>
name: "main"
BoxLayout:
Button:
text: "Press"
on_release:
app.root.current = "first"
First.kv
<FirstWindow#Screen>:
name: "first"
BoxLayout:
orientation: "vertical"
Label:
text: "Enter Unique Text for Saving"
font_size: 20
text_size: self.width, None
halign: 'center'
TextInput:
id: unique
hint_text: 'example: Stand25'
Button:
text: "Press"
on_release:
app.root.current = "second"
Second.kv
<SecondWindow#Screen>:
name: "second"
BoxLayout:
orientation: "vertical"
Label:
text: "Unique Text"
font_size: 20
text_size: self.width, None
halign: 'center'
Label:
text: root.get_unique_text()
font_size: 16
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
color: 0,0,0,1
Button:
text: "Go Back"
on_release:
app.root.current = "first"
Another approach is to use the on_enter() method of a Screen in order to fetch the text. This also requires an id for the unique Label:
<SecondWindow#Screen>:
name: "second"
BoxLayout:
orientation: "vertical"
Label:
text: "Unique Text"
font_size: 20
text_size: self.width, None
halign: 'center'
Label:
id: unique # added id
# text: root.get_unique_text()
font_size: 16
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
color: 0,0,0,1
Button:
text: "Go Back"
on_release:
app.root.current = "first"
Just add an on_enter() method to the SecondWindow class:
class SecondWindow(Screen):
def on_enter(self, *args):
self.ids.unique.text = self.get_unique_text()
def get_unique_text(self):
x = self.manager.get_screen("first")
y = x.ids.unique.text
return str(y)
In your Second.kv you can reference the text of the TextInput in the First.kv by making a couple changes to the kv files. First, in the main.kv, add an id for the FirstWindow (and eliminate the SecondWindow for now):
WindowManager:
MainWindow:
FirstWindow:
id: first # added id
# SecondWindow: # this gets added later
<MainWindow>
name: "main"
BoxLayout:
Button:
text: "Press"
on_release:
app.root.current = "first"
Then, in the Second.kv, set up the reference to the text of the TextInput:
<SecondWindow#Screen>:
name: "second"
BoxLayout:
orientation: "vertical"
Label:
text: "Unique Text"
font_size: 20
text_size: self.width, None
halign: 'center'
Label:
text: app.root.ids.first.ids.unique.text # reference to unique text
font_size: 16
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
color: 0,0,0,1
Button:
text: "Go Back"
on_release:
app.root.current = "first"
Since the kv for SecondWindow uses app.root, it will cause an error if SecondWindow is instantiated before the root widget of the App is assigned. To avoid that, add the SecondWindow after a slight delay:
class MyApp(App):
def build(self):
Clock.schedule_once(self.add_second_screen)
return kv_main
def add_second_screen(self, dt):
self.root.add_widget(SecondWindow())

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.

Kivy POPUP and Button text

First I'm new to kivy. myApp is based on kivy-example/demo/kivycatlog and I was modifying PopupContainer.kv, but my code doesn't work.
PopupContainer.kv
BoxLayout:
id: bl
orientation: "vertical"
popup: popup.__self__
canvas:
Color:
rgba: .18, .18, .18, .91
Rectangle:
size: self.size
pos: self.pos
Button:
id: showPopup1
text: 'press to show popup'
on_release: root.popup.open()
Button:
id: showPopup2
text: 'press to show popup'
on_release: root.popup.open()
Popup:
id: popup
on_parent: if self.parent == bl: bl.remove_widget(self)
title: "An example popup"
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'vertical'
Button:
id: accept
text: "yes"
on_release: status.text = self.text
Button:
id: cancel
text: "no"
on_release: status.text = self.text
Label:
id: status
text: "yes or no?"
Button:
text: "press to dismiss"
on_release: popup.dismiss()
I want to change the text(showPopup) when I click on "yes" or "no"
on the showPopup's text.
You could get the text of your ShowPopup's buttons from your code. I mean declare a variable in your code named popups_text and in your .kv file try accesing it using root.popups_text. then create a method in your code that changes this text every time the button is pressed.

Categories