I can't read the value of text input in Kivy - python

My problem is when I want to display the value given by the user in the Text input text field.
When I want to get the text value from the input I get an empty value and I cannot display anything in the label field .
Here is my code :
The kv file :
MainGridLayout:
<MainGridLayout>:
cols: 1
rows: 2
BoxLayout:
orientation: 'vertical'
TextInput:
id: my_text_input
text: root.text_input_1
hint_text :'Operations'
multiline:False
pos_hint: {'center_x': 0.5, 'center_y': 0.705}
size_hint: 0.95, 0.5
font_size: '30dp'
Label:
text: root.Display_text
font_size: '45dp'
StackLayout:
Button:
text:"+"
spacing: .2, .2
size: 85, 85
size_hint: None, None
on_press: root.on_button_plus()
The py file :
from kivy.app import App
from kivy.properties import StringProperty
from kivy.uix.gridlayout import GridLayout
# different layouts:
class MainGridLayout(GridLayout):
text_input_1 = StringProperty()
Display_text = StringProperty()
def on_button_plus(self):
print(f'{self.text_input_1}')
# run application:
class CalculatorApp(App):
pass
CalculatorApp().run()

I have created a function in MainGridLayout, on_new_text, that takes as a parameter a TextInput and updates text_input_1 with its value.
In the kv file I have set the on_text property of the TextInput to the on_new_text function and gave the TextInput as a parameter. Every time you modify the text input, the on_new_text function will be called, modifying the text_input_1 property.
You can find more properties like on_text in the kivy documentation.
The kv file:
MainGridLayout:
<MainGridLayout>:
cols: 1
rows: 2
BoxLayout:
orientation: 'vertical'
TextInput:
id: my_text_input
hint_text :'Operations'
multiline:False
pos_hint: {'center_x': 0.5, 'center_y': 0.705}
size_hint: 0.95, 0.5
font_size: '30dp'
on_text: root.on_new_text(self)
Label:
text: root.Display_text
font_size: '45dp'
StackLayout:
Button:
text:"+"
spacing: .2, .2
size: 85, 85
size_hint: None, None
on_press: root.on_button_plus()
The py file:
from kivy.app import App
from kivy.properties import StringProperty
from kivy.uix.gridlayout import GridLayout
# different layouts:
class MainGridLayout(GridLayout):
text_input_1 = StringProperty()
Display_text = StringProperty()
def on_new_text(self, text_input):
self.text_input_1 = text_input.text
def on_button_plus(self):
print(f'{self.text_input_1}')
class CalculatorApp(App):
pass
CalculatorApp().run()

Actually, you don't need the variables text_input_1 and Display_text. To display the text from the my_text_input on the label you can add text: my_text_input.text instead of text: root.Display_text. Now, when the text of my_text_input changes, the label's text will change automatically and you don't need any functions. In on_button_plus() method you can do the same and print my_text_input's text using its text property (from all MainGridLayout's ids you take only my_text_input and print its text). The line text: root.text_input_1 unnecessary, too.
Here is my editted version of your code:
The .py file
from kivy.app import App
from kivy.properties import StringProperty
from kivy.uix.gridlayout import GridLayout
class MainGridLayout(GridLayout):
def on_button_plus(self):
print(f'{self.ids.my_text_input.text}')
class CalculatorApp(App):
pass
CalculatorApp().run()
The .kv file
MainGridLayout:
<MainGridLayout>:
cols: 1
rows: 2
BoxLayout:
orientation: 'vertical'
TextInput:
id: my_text_input
hint_text :'Operations'
multiline:False
pos_hint: {'center_x': 0.5, 'center_y': 0.705}
size_hint: 0.95, 0.5
font_size: '30dp'
Label:
text: my_text_input.text # change the text automatically
font_size: '45dp'
StackLayout:
Button:
text:"+"
spacing: .2, .2
size: 85, 85
size_hint: None, None
on_press: root.on_button_plus()

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

Auto Sweep/Scroll Carousel in KivyMD (Python)

I want to make a 2 Slide Carousel with auto scrolling in KivyMD with Python. On Startup, the App starts from the The first Slide of Carousel and it should be changed to 2nd slide after 3 seconds.
Here is my Code
.kv
<WelcomeScreen>:
MDFloatLayout:
md_bg_color : 1, 1, 1, 1
Carousel:
id: caraousel
on_current_slide: app.current_slide(self.index)
MDFloatLayout:
Image:
source: "Assets/1.png"
pos_hint: {"center_x": .5, "center_y": .6}
size_hint: .3, .3
MDLabel:
text: "Slide 1"
pos_hint: {"center_y": .087}
halign: "center"
font_name: "Poppins-Light"
font_size: "14sp"
color: rgba(135, 143, 158, 200)
MDFloatLayout:
Image:
source: "Assets/2.jpg"
pos_hint: {"center_x": .5, "center_y": .7}
size_hint: .8, .8
MDLabel:
text: "Slide 2"
pos_hint: {"center_y": .47}
halign: "center"
font_name: "Poppins-Regular"
font_size: "25px"
color: rgba(1, 3, 23, 225)
.py
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen,ScreenManager, NoTransition
from kivy.utils import rgba
from kivy.core.window import Window
from kivy.core.text import LabelBase
from kivy.clock import Clock
Window.size = (310, 580)
class WelcomeScreen(Screen):
pass
class AppApp (MDApp):
def build(self):
return Builder.load_file('app.kv')
def current_slide(self, index):
pass
AppApp().run()
Anyone can help me with this Issue? Thanks in Advance.
You can use method Clock.schedule_interval to perform automatic loading of sliders. Trigger that action from anywhere in your code, for example to make it happen from the very beginning, trigger it from the method on_start of class app as,
app.kv file.
<WelcomeScreen>:
MDFloatLayout:
md_bg_color : 1, 1, 1, 1
Carousel:
id: caraousel
on_current_slide: app.current_slide(self.index)
MDFloatLayout:
Image:
source: "Assets/1.png"
pos_hint: {"center_x": .5, "center_y": .6}
size_hint: .3, .3
MDLabel:
text: "Slide 1"
pos_hint: {"center_y": .087}
halign: "center"
# font_name: "Poppins-Light"
font_size: "14sp"
color: rgba(135, 143, 158, 200)
MDFloatLayout:
Image:
source: "Assets/2.jpg"
pos_hint: {"center_x": .5, "center_y": .7}
size_hint: .8, .8
MDLabel:
text: "Slide 2"
pos_hint: {"center_y": .47}
halign: "center"
# font_name: "Poppins-Regular"
font_size: "25px"
color: rgba(1, 3, 23, 225)
main.py file.
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen,ScreenManager, NoTransition
from kivy.utils import rgba
from kivy.core.window import Window
from kivy.core.text import LabelBase
from kivy.clock import Clock
Window.size = (310, 580)
class WelcomeScreen(Screen):
pass
class AppApp(MDApp):
def build(self):
Builder.load_file('app.kv')
return WelcomeScreen()
def on_start(self):
# Access the carousel.
carousel = self.root.ids.caraousel
# Set infinite looping (optional).
carousel.loop = True
# Schedule after every 3 seconds.
Clock.schedule_interval(carousel.load_next, 3.0)
def current_slide(self, index):
pass
AppApp().run()
Update:
Try avoiding the App's instance name as AppApp and related .kv file as app.kv simultaneously, that might cause problems during auto .kv loading. However loading the file explicitly and then returning the root from method build (or declaring in .kv file) should work.

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 Selection on Focus

I'm trying to have kivy select the text of a TextInput widget on focus but when I try it seems to select it when it unfocuses and retains the selection. Any ideas how I can select it on focus and on unfocus deselect? I've attached my code below if someone wants to have a play around.
kv file:
<TextInput>:
size_hint: 0.9, 0.5
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
multiline: False
<Button>:
text: "Press Me"
size_hint: (0.1, 0.5)
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
<MainLayout>:
canvas.before:
Color:
rgba: 0.15, 0.15, 0.16, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
padding: 10
BoxLayout:
padding: 10
TextInput:
text: "Directory"
Button:
text: "Browse"
on_press: root.browse_btn()
BoxLayout:
padding: 10
TextInput:
text: "Prefix"
on_focus: self.select_all()
TextInput:
text: "File"
on_focus: self.select_all()
TextInput:
text: "Suffix"
on_focus: self.select_all()
BoxLayout:
padding: 10
Button:
id: button_one
text: "Confirm"
on_press: root.confirm_btn()
Button:
text: "Cancel"
on_press: root.cancel_btn()
python file:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivy.config import Config
Config.set('graphics', 'resizable', 0)
class MainLayout(BoxLayout):
button_id = ObjectProperty(None)
def browse_btn(self):
print("Hey")
def confirm_btn(self):
print("Confirm")
def cancel_btn(self):
print("Cancel")
class BatchRenameApp(App):
def build(self):
self.title = "Batch File Rename"
Window.size = (750, 250)
return MainLayout()
if __name__ == '__main__':
app = BatchRenameApp()
app.run()
Well hidden in the TextInput documentation:
Selection is cancelled when TextInput is focused. If you need to show
selection when TextInput is focused, you should delay (use
Clock.schedule) the call to the functions for selecting text
(select_all, select_text).
So, in your kv, start by importing Clock:
#: import Clock kivy.clock.Clock
Then you can use it in a TextInput rule:
TextInput:
text: "Prefix"
on_focus: Clock.schedule_once(lambda dt: self.select_all()) if self.focus else None
The if self.focus makes sure the select_all only happens when the TextInput gains focus.

Python : How add a datepicker in .kv file

Can anyone tell me how to add a date picker or kivy calendar on date TextBox?
I have two file test.py and test.kv file.
test.py
import kivy
import sqlite3 as lite
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.label import Label
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (400, 125)
class Testing(Screen):
pass
class Testing(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
Testing().run()
test.kv
Testing:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
padding: 10, 10
spacing: 10, 10
size_hint_x: .55
Label:
text: "Date"
text_size: self.size
valign: 'middle'
size_hint_x: .2
TextInput:
size_hint_x: .3
BoxLayout:
orientation: "horizontal"
padding : 10, 0
spacing: 10, 10
size_hint: .5, .7
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
on_release:
root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
.kv file
#:import MDTextField kivymd.uix.textfield.MDTextField
MDTextField:
id: set_date
hint_text: 'Start Date'
write_tab: False
on_focus: root.setDate()
.py file
from kivymd.uix.picker import MDDatePicker
def setDate(self,dobj):
self.ids.set_date.text = str(dobj)
pass
def fromDate(self):
self.foc = self.ids.set_date.focus
if(self.foc==True):
MDDatePicker(self.setFDate).open()
else:
print("not")

Categories