I want to write a mobile app with a KivyMD like Bottom Sheet Menu. My problem with KivyMD Buttom Sheet is, when I click the button to open it, takes very long time (depends on the menu length) because the list is generated by calling the function every time the button was pressed. So I want to write my own solution for this.
In my kv file I manually added 20 buttons to see, it's everything work. But i didn't find the way to do it in python file with loop.
Can anyone help me please to add more than 30 buttons to modalview to be scrollable?
Here is my python file:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.core.window import Window
Builder.load_file('mylayout.kv')
Window.size = (350, 700)
class MyLayout(BoxLayout):
pass
class MainApp(App):
def build(self):
return MyLayout()
MainApp().run()
an my kv file:
#:import Factory kivy.factory.Factory
<MyPopup#ModalView>
auto_dismiss: True
size_hint: 1, 0.5
pos_hint: {'x': 0, 'top': 0.5}
background_color: 0,0,0,0
background_normal: ''
canvas.before:
Color:
rgba: 48/150,84/150,150/150,1
Rectangle:
size: self.size
pos: self.pos
ScrollView:
#do_scroll_x: False
GridLayout:
id: container1
cols: 1
size_hint: None, None
size: root.width, 1200
pos_hint: {'center_x': .5, 'center_y': .5}
MyButton:
text: '1'
on_press:
root.dismiss()
print(1)
MyButton:
text: '2'
on_press:
root.dismiss()
print(2)
MyButton:
text: '3'
on_press:
root.dismiss()
print(3)
MyButton:
text: '4'
on_press:
root.dismiss()
print(4)
MyButton:
text: '5'
on_press:
root.dismiss()
print(5)
MyButton:
text: '6'
on_press:
root.dismiss()
print(6)
MyButton:
text: '7'
on_press:
root.dismiss()
print(7)
MyButton:
text: '8'
on_press:
root.dismiss()
print(8)
MyButton:
text: '9'
on_press:
root.dismiss()
print(9)
MyButton:
text: '10'
on_press:
root.dismiss()
print(10)
MyButton:
text: '11'
on_press:
root.dismiss()
print(11)
MyButton:
text: '12'
on_press:
root.dismiss()
print(12)
MyButton:
text: '13'
on_press:
root.dismiss()
print(13)
MyButton:
text: '14'
on_press:
root.dismiss()
print(14)
MyButton:
text: '15'
on_press:
root.dismiss()
print(15)
MyButton:
text: '16'
on_press:
root.dismiss()
print(16)
MyButton:
text: '17'
on_press:
root.dismiss()
print(17)
MyButton:
text: '18'
on_press:
root.dismiss()
print(18)
MyButton:
text: '19'
on_press:
root.dismiss()
print(19)
MyButton:
text: '20'
on_press:
root.dismiss()
print(20)
<MyLayout>
orientation: 'vertical'
size: root.width, root.height
Label:
size_hint: 1, 0.9
text: 'main'
font_size: 24
Button:
size_hint: 1, 0.1
text: 'menu'
font_size: 24
on_release: Factory.MyPopup().open()
<MyButton#Button>
background_color: 0,0,0,0
background_normal: ''
canvas.before:
Color:
rgba: (48/255,84/255,150/255,1) if self.state == 'normal' else (43/255,108/255,229/255,1)
Rectangle:
size: self.size
pos: self.pos
In order to build the MyPopup filled with MyButtons, you must either define those classes in the python code or use Factory to create the instances. Here is a modified version of your kv to do this:
<MyPopup#ModalView>
auto_dismiss: True
size_hint: 1, 0.5
pos_hint: {'x': 0, 'top': 0.5}
background_color: 0,0,0,0
background_normal: ''
canvas.before:
Color:
rgba: 48/150,84/150,150/150,1
Rectangle:
size: self.size
pos: self.pos
ScrollView:
#do_scroll_x: False
GridLayout:
id: container1
cols: 1
size_hint: None, None
width: root.width
height: self.minimum_height # let the GridLayout set its own height as needeed
pos_hint: {'center_x': .5, 'center_y': .5}
<MyLayout>
orientation: 'vertical'
size: root.width, root.height
Label:
size_hint: 1, 0.9
text: 'main'
font_size: 24
Button:
size_hint: 1, 0.1
text: 'menu'
font_size: 24
# on_release: Factory.MyPopup().open()
on_release: app.open_popup() # call app method to build MyPopup and fill it
<MyButton#Button>
background_color: 0,0,0,0
background_normal: ''
size_hint_y: None
height: 20
canvas.before:
Color:
rgba: (48/255,84/255,150/255,1) if self.state == 'normal' else (43/255,108/255,229/255,1)
Rectangle:
size: self.size
pos: self.pos
Note that the GridLayout height is set to self.minimum_height to allow for any number of MyButton children, and the MyButton height is set to a fixed value (so that GridLayout can calculate the minimum height). Also, the import of Factory is no longer needed in the kv.
The modified python code:
from kivy.app import App
from kivy.factory import Factory
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.core.window import Window
Builder.load_file('mylayout.kv')
Window.size = (350, 700)
class MyLayout(BoxLayout):
pass
class MainApp(App):
def build(self):
return MyLayout()
def open_popup(self, *args):
# create the popup (must use Factory since MyPopup is defined in kv)
self.popup = Factory.MyPopup()
# fill the GridLayout
grid = self.popup.ids.container1
for i in range(60):
grid.add_widget(Factory.MyButton(text=str(i), on_press=self.myButtPress))
# open popup
self.popup.open()
def myButtPress(self, butt):
print(butt.text)
self.popup.dismiss()
MainApp().run()
Related
I want to update MDRectangleFlatIconButton's text. It changes with a new text but when the new text is longer than previous text, then the text fits in two lines.
When i use a normal button, the new text fits in one line with proper adjustment.
but Since there is a Icon in MDRectangleFlatIconButton, when a new text is longer than previous text, the text fits in a two line.
To run the program,
Add a new app name which is longer than "Info" inside "Info" button's popup window, then click "Update Top Bar's name". Then, it updated title and the text of "Info" button at the front main App.
I have tried to change this by adding button's text_size: self.width, valign:"center", haling: "center", or manually adding text_size: cm(10), cm(10).
Also, i tried with on_release: "app.root.ids.bt_information.text_size = self.width, None
but nothing works so far.
I greatly appreciate your help.
Python code
'''
from kivy.uix.widget import Widget
'''Setting the size of first window for program'''
from kivy.config import Config #another way of setting size of window
Config.set('graphics', 'width', '600') # from kivy.core.window import Window
Config.set('graphics', 'height', '750') # Window.size = ("600", "750")
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.factory import Factory
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
Builder.load_file('new_window_popup.kv')
class Dex(Popup):
pass
class Remi(Popup):
pass
class Info(Popup):
pass
class MyLayout(Widget):
pass
class AwesomeApp(MDApp):
def build(self):
self.title = "My house"
return MyLayout()
if __name__ == '__main__':
AwesomeApp().run()
'''
kivyfile: new_window_popup.kv
'''
#:import Factory kivy.factory.Factory
#:import MDRaisedButton kivymd.uix.button
<Dex>:
auto_dismiss: False
size_hint: 1, 1
title: "Weight-Based Dose Calculator "
canvas.before:
Color:
rgba: (0,1,0,1)
Rectangle:
pos:self.pos
size:self.size
BoxLayout:
orientation: "vertical"
size:root.width, root.height
Label:
text: "Dex 1"
Button:
text: "Close"
font_size: 24
on_release: root.dismiss()
<Remi>:
auto_dismiss: False
size_hint: 1, 1
title: "Weight-Based Dose Calculator "
canvas.before:
Color:
rgba: (0,1,0,1)
Rectangle:
pos:self.pos
size:self.size
BoxLayout:
orientation: "vertical"
size:root.width, root.height
Label:
text: "Remi"
Button:
text: "Close"
font_size: 24
on_release: root.dismiss()
<Info>:
appName:appName
auto_dismiss: False
size_hint: 1, 1
title: "Change Info"
canvas.before:
Color:
rgba: (0,1,0,1)
Rectangle:
pos:self.pos
size:self.size
BoxLayout:
orientation: "vertical"
size:root.width, root.height
Label:
text: "What is your App name?"
BoxLayout:
orientation: "horizontal"
MDTextField:
id: appName
hint_text: "App Name"
color_mode: 'primary'
current_hint_text_color: 1,1,1,1
hint_text_color_focus: 1,1,1,.9
line_color_focus: 1,1,1,1
font_size: '25sp'
text_color_normal: 1,1,1,.9
text_color_focus: 0,0,1,.9
focus: True
write_tab: False
Button:
text: "Update Top Bar\'s name"
font_size: 24
size_hint: .8, .2
# on_release: root.updateName()
on_release:
app.title = appName.text
app.root.ids.bt_information.text = appName.text
Button:
text: "Close"
font_size: 24
on_release: root.dismiss()
<MyLayout>
MDBoxLayout:
orientation:"vertical"
size: root.width, root.height
MDRaisedButton:
text: "Dex"
font_size: 32
text_color: 0,0,0,.9
size_hint: 1,.5
on_press: Factory.Dex().open()
MDRaisedButton:
text: "Remi"
font_size: 32
size_hint: 1,.5
on_press: Factory.Remi().open()
MDRectangleFlatIconButton:
id: bt_information
text: "Info"
icon: "youtube-studio"
font_size: 32
size_hint: 1,.2
text_size: self.width, None
md_bg_color: 0.95,0.61,0.73,1
on_press: Factory.Info().open()
'''
This is how my program looks right now.
How can I position my button "Log in" to always be horizontally aligned with center? I've tried looking on Stack Overflow about similar stuff but nothing worked for me... If anyone can help me, I would be really thankful.
Here's my python code:
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.gridlayout import GridLayout
import kivy.properties as kyprops
from kivy.uix.widget import Widget
from kivy.uix.image import Image
Builder.load_file("main.kv")
Window.clearcolor = (1,1,1,1)
# Declare both screens
class LoginScreen(Screen):
#txt_inpt = kyprops.ObjectProperty(None)
#def __init__(self):
pass
class InfoScreen(Screen):
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(LoginScreen(name='Login'))
sm.add_widget(InfoScreen(name='Info'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
Here is my .kv code:
#:import C kivy.utils.get_color_from_hex
<LoginScreen>:
RelativeLayout:
txt_inpt: txt_inpt
canvas:
Color:
rgba: C('#336699')
Line:
width: 2
rectangle: (0,self.height-50,self.width,0)
id: linija
Ellipse:
pos: self.width- 35, self.height-15
size: 7 , 7.0000000001
angle_start: 0
angle_end: 360
Ellipse:
pos: self.width- 35, self.height-27
size: 7 , 7.0000000001
angle_start: 0
angle_end: 360
Ellipse:
pos: self.width- 35, self.height-39
size: 7 , 7.0000000001
angle_start: 0
angle_end: 360
TextInput:
id: txt_inpt
password: True
multiline: False
hint_text: 'Username'
hint_text_color: C('#b3ccff')
size_hint_x: 0.9
size_hint_y: None
pos_hint: {"x":0.05, "top":0.8}
background_color: (1,1,1,0.2)
on_text_validate: root.manager.current = 'Info'
height: 30
pos: 300,60
TextInput:
id: txt_inpt
password: True
multiline: False
hint_text: 'Password'
hint_text_color: C('#b3ccff')
size_hint_x: 0.9
size_hint_y: None
pos_hint: {"x":0.05, "top":0.7}
background_color: (1,1,1,0.2)
on_text_validate: root.manager.current = 'Info'
height: 30
pos: 300,60
BoxLayout:
width: 1
pos: self.parent.pos # important!
orientation: 'vertical'
halign: 'center'
Button:
on_press: root.manager.current = 'Info'
background_color: C('#336699')
pos: self.pos
size: self.size
size: 80,30
size_hint: None, None
## NOTE: pos_hint: {"x":0.45, "top":0.6}
font_name: 'Droid.otf'
text: 'Log in'
<InfoScreen>:
BoxLayout:
Button:
text: 'My settings button'
Button:
text: 'Back to menu'
on_press: root.manager.current = 'Login'
Your line in kv:
pos: self.parent.pos # important!
is positioning the BoxLayout in the lower left corner of the RelativeLayout
You can center it by using pos_hint and minimum_width:
BoxLayout:
# width: 1
# pos: self.parent.pos # important!
pos_hint: {'center_x':0.5, 'y':0}
size_hint_x: None
width: self.minimum_width
orientation: 'vertical'
I have an App with three toggle buttons in a fixed header that is an outside indented layout for screen manager. On initialisation, the Import screen must show i.e. self.ids.scrn_man.current = 'import_scn" and when a toggle button is pushed a next screen should show i.e. on_state: scrn_man.current = "settings_scrn".
But for some reason, only the header is showing and the screens do not want to transition. I don't get any errors.
I tried different layouts as my Apps main class inheritance including, FloatLayout, StackLayout and BoxLayout. I also made the header fixed with AnchorLayout and use a different layout as the inline layout for ScreenManager. If I remove the ScreenManager I see my widgets, but of course, I cannot transition. I did at first try using TabbedPanel to house my different widgets but I encountered a constant RefError: weak object reference if I added too many widgets (but that's not for now). So I re-designed with something I knew worked on a previous App albeit less complex.
Here is my faulty code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.properties import StringProperty, ObjectProperty
Builder.load_string("""
<RoundedButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (1,.6,0,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<RoundedCancelButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (1,.2,.2,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<RoundedAcceptButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (.2,1,.6,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<TabbedContainer#ToggleButton>:
background_color: (1, .5, 0, 1)
background_normal: ''
size_hint_y: None
height: 50
size_hint_x: (1 / 3)
spacing: 30
<Tab>:
canvas.before:
Color:
rgba: (.89, .89, .89, 1)
Rectangle:
size: self.size
pos: self.pos
orientation: 'lr-tb'
BoxLayout:
orientation: 'horizontal'
size_hint_y: None
height: 30
canvas.before:
Color:
rgba: (1, .3, 0, 1)
Rectangle:
size: self.size
pos: self.pos
Label:
text: 'Test'
color: (1, 1, 1, 1)
size_hint_x: 1
StackLayout:
orientation: 'lr-tb'
Label:
text: ''
size_hint_x: 1
size_hint_y: None
height: 10
TabbedContainer:
id: import_tog
text: 'Import'
state: 'down'
group: 'admin_navs'
on_state: root.change_screen(self)
TabbedContainer:
id: calculate_tog
text: 'Calculate'
group: 'admin_navs'
on_state: root.change_screen(self)
TabbedContainer:
id: settings_tog
text: 'Settings'
group: 'admin_navs'
on_state: root.change_screen(self)
BoxLayout:
id: ui_content
padding: 10
ScreenManager: #Problem here I think
id: scrn_man
Screen:
id: import_scrn
name: 'import_scrn'
StackLayout:
orientation: 'lr-tb'
Label:
text: ''
size_hint_x: 1
Label:
text: ''
size_hint_x: 0.2
RoundedButton:
text: 'Choose File'
size_hint_x: 0.2
TextInput:
id: get_file
readonly: True
size_hint_x: 0.5
Label:
text: ''
size_hint_x: 0.1
Label:
text: ''
size_hint_x: 0.2
RoundedButton:
text: 'Import'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.6
StackLayout:
id: import_data_content
orientation: 'lr-tb'
size_hint_y: None
height: 90
Screen:
id: calculate_scrn
name: 'calculate_scrn'
Screen:
id: settings_scrn
name: 'settings_scrn'
StackLayout:
orientation: 'lr-tb'
size_hint_x: 0.5
Label:
text: ''
size_hint_x: 0.1
Button:
text: 'Add Employee'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.2
Button:
text: 'CSV'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.3
BoxLayout:
orientation: 'horizontal'
size_hint_x: 0.5
Label:
text: 'In Time'
size_hint_x: 0.7
TextInput:
size_hint_x: 0.3
Label:
text: 'Out Time'
size_hint_x: 0.7
TextInput:
size_hint_x: 0.3
""")
class TabbedContainer(ToggleButton):
pass
class FileChoosePopup(Popup):
load = ObjectProperty()
class RoundedButton(Button):
pass
class RoundedCancelButton(Button):
pass
class RoundedAcceptButton(Button):
pass
class Tab(StackLayout):
file_path = StringProperty("No file chosen")
the_popup = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
#load import window on initialisation
import_window = self.ids.import_scrn
self.ids.scrn_man.current = 'import_scrn'
def change_screen(self, instance):
if instance.text == 'Import':
self.ids.scrn_man.current = 'import_scrn'
elif instance.text == 'Calculate':
self.ids.scrn_man.current = 'calculate_scrn'
else:
self.ids.scrn_man.current = 'settings_scrn'
class TestApp(App):
def build(self):
return Tab()
if __name__ == '__main__':
TestApp().run()
I expect that the import screen must show on initialisation and screens transition on toggle button state: down. Can someone please give me some advice on how to make my App act as explained above?
Your screens are loading correctly according to your settings. You need to review your entire kv string looking at your size_hint settings. Check each item that contains children and make sure that the total of size_hint_x for its children is less than or equal to 1.0 and the same for size_hint_y.
I am new to python/Kivy.
I have two files test.py and test.ky.
Now I am using two static row with serial number 1 and 2.
Can anyone tell me?
How to add row dynamic when click on '+add more' button.Now 2 row shows which are static row with serial number increment. I want add row dynamic 1 to 10 with serial number increment.
test.py
import kivy
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (450, 525)
class display(Screen):
def add_more(self):
print('test')
class test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
test().run()
test.kv
display:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
Button:
size_hint_x: .2
text: "+Add More"
valign: 'bottom'
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
Label:
size_hint_x: .2
text: "SN"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value"
valign: 'bottom'
BoxLayout:
orientation: "horizontal"
spacing: 0, 5
Button:
text: '1'
size_hint_x: .2
TextInput:
size_hint_x: .8
BoxLayout:
orientation: "horizontal"
spacing: 0, 5
Button:
text: '2'
size_hint_x: .2
TextInput:
size_hint_x: .8
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()
Can someone help me?
You can make a custom class for Row and Rows, then have a method adding rows.
I modified your example a bit. Try this:
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.boxlayout import BoxLayout
from kivy.properties import StringProperty
Window.size = (450, 525)
class display(Screen):
def add_more(self):
self.ids.rows.add_row()
class Row(BoxLayout):
button_text = StringProperty("")
class Rows(BoxLayout):
orientation = "vertical"
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class test(App):
def build(self):
self.root = Builder.load_string(KV)
return self.root
KV = """
<Row>:
orientation: "horizontal"
spacing: 0, 5
Button:
text: root.button_text
size_hint_x: .2
TextInput:
size_hint_x: .8
display:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
Button:
size_hint_x: .2
text: "+Add More"
valign: 'bottom'
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
Label:
size_hint_x: .2
text: "SN"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value"
valign: 'bottom'
Rows:
id: rows
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()
"""
test().run()
I am trying to create a checkbox in my float layout area. I am getting the checkbox to generate but every time I click it goes from True to False even if it not on the box. Could someone provide some insight?
My code:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.checkbox import CheckBox
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
#######``Windows``#######
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
def add(self, *args):
a = self.ids["a"].text
a = int(a)
self.ids["adds"]
plus = 1 + a
print plus
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("GUI_Style.kv")
class MainApp(App):
def build(self):
return presentation
if __name__ == "__main__":
MainApp().run()
My KV File:
#: import NoTransition kivy.uix.screenmanager.NoTransition
ScreenManagement:
transition: NoTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
background_color: 0.5, 1, 0.22, 1
name: "main"
FloatLayout:
Button:
text: "Quit"
font_size: 50
color: 0,1,0,1
font_size: 25
size_hint: 0.3,0.2
pos_hint: {"x":0, "y":0}
on_release: app.window().stop()
Button:
on_release: app.root.current = "other"
text: "Next Screen"
font_size: 50
color: 0,1,0,1
font_size: 25
size_hint: 0.3,0.2
pos_hint: {"right":1, "top":1}
<AnotherScreen>:
name: "other"
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
FloatLayout:
CheckBox:
pos_hint: {"x":0.2, "y":0.2}
on_release: True
TextInput:
id: a
font_size: 25
password: True
pos_hint: {"x":0.5, "y":0.5}
size_hint: 0.3,0.2
text: "Insert Side A here"
Button:
id: adds
background_color: 0,0,1,1
color: 0,1,0,1
font_size: 25
on_release: root.add()
pos_hint: {"x":0, "y":0}
size_hint: 0.3,0.2
text: "plus"
Button:
color: 0,1,0,1
background_color: 0,0,1,1
font_size: 25
size_hint: 0.3,0.2
text: "Back Home"
on_release: app.root.current = "main"
pos_hint: {"right":1, "top":1}
Try placing the CheckBox in a Widget and it works. I mean:
FloatLayout:
Widget:
CheckBox:
pos_hint: {"x":0.2, "y":0.2}
on_release: True
TextInput:
id: a
font_size: 25
password: True
pos_hint: {"x":0.5, "y":0.5}
size_hint: 0.3,0.2
text: "Insert Side A here"
Button:
id: adds
background_color: 0,0,1,1
color: 0,1,0,1
font_size: 25
on_release: root.add()
pos_hint: {"x":0, "y":0}
size_hint: 0.3,0.2
text: "plus"
of course it ruins your layout but it solves the problem you are having.