I get:
AttributeError: 'Carousel' object has no attribute 'switch_on'
error whenever I try to click on the button
-------main.py----------
class main(App):
def build(self):
class SampBoxLayout(BoxLayout):
# For Switch
def switch_on(self, instance, value):
if value is True:
print("Switch On")
else:
print("Switch Off")
return Carousel()
sample_app = kv_main()
sample_app.run()
----------main.kv--------------
:
Label:
text: "Page 1"
size_hint: 1, .1
width :100
SampBoxLayout:
# ----------Switch ----------
BoxLayout:
BoxLayout:
orientation: "horizontal"
size_hint_x: .25
CustLabel:
text: "On / Off"
Switch:
id: switch_id
on_active: root.switch_on(self, self.active)# <--need help on this
Label:
text: "Page 2"
size_hint: 1, .1
width :100
Button:
text: "Button 2.1"
size_hint: None, None
width :100
Label:
text: "Page 3"
size_hint: 1, .1
width :100
Button:
text: "Button 3.1"
size_hint: None, None
width :100
You are using root.switch_on. As the error indicates, your root class is the carousel. Since SampBoxLayout is not root, you should give SampBoxLayout an id, and call it with it´s id.
Edited from your example:
SampBoxLayout:
id: samp
BoxLayout:
BoxLayout:
orientation: "horizontal"
size_hint_x: .25
CustLabel:
text: "On / Off"
Switch:
id: switch_id
on_active: samp.switch_on(self, self.active)
I don't know if you did something wrong when posting this, or if your code really looks like this. But you should not define classes inside your app class. Keep the classes on top level to access them in kv.
And your kv code is unusual. You have your widgets in a label.
Related
I would like to build the following simple design in a .kv file.
It is made of 3 parts :
One top-left Anchor Layout which is made up of a Grid Layout of 3 columns. I want its width to be equal to 20% of the window's with and its height to be equal to 75% of the window's height.
One top-right Anchor Layout which is made up of a vertically-oriented Box Layout. I want its width to be equal to 80% of the window's with and its height to be equal to 75% of the window's height.
One bottom-left Anchor Layout which is empty for the moment. I want its height to be 25% of the window's height.
These three parts are themselves included in an AnchorLayout.
I tried to translate this design into a .kv file as follows.
#:kivy 1.11.1
<Example>:
anchor_x: "center"
anchor_y: "center"
AnchorLayout:
anchor_x: "left"
anchor_y: "top"
size_hint: (0.2, 0.75)
GridLayout:
cols: 3
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
AnchorLayout:
anchor_x: "right"
anchor_y: "top"
size_hint: (0.8, 0.75)
BoxLayout:
orientation: "vertical"
Label:
text: "HELLO..."
Label:
text: "WORLD..."
AnchorLayout:
anchor_x: "left"
anchor_y: "bottom"
size_hint: (1, 0.25)
Label:
text: "FOOTER"
In case it matters, here is the code of my .py file as well.
# Importing Kivy
import kivy
kivy.require("1.11.1")
# Importing kivy libraries
from kivy.app import App
from kivy.uix.anchorlayout import AnchorLayout
from kivy.lang import Builder
# Importing external libraries
# Import kv files
Builder.load_file("example.kv")
# Root widget of the application
class Example(AnchorLayout):
pass
# Application class
class TestApp(App):
def build(self, **kwargs):
return Example()
# Launch the application
if __name__=="__main__":
app = TestApp()
app.run()
The output does not look as I expected as shown on the picture below :
I don't get it. Because the AnchorLayout is a subclass of the Widget class and is itself included within a Layout, its size_hint property should enable me to define its size.
What am I missing here ? Thanks in advance!
Problem - design centered
The design is placed in the center.
Root Cause
The root is an AnchorLayout with value 'center' for both anchor_x and anchor_y. Therefore, all its children (the AnchorLayouts) are placed in respect to the root.
Below is a view of your design in different colours for visualization.
AnchorLayout
The AnchorLayout aligns its children to a border (top, bottom, left, right) or center.
Solution
There are three possible solutions to your design. The preference is method 1.
Method 1 - No AnchorLayouts
This method replace all AnchorLayouts with BoxLayouts. It use one less AnchorLayout widget which makes the app more resource efficient i.e. use less memory and the app is smaller.
Snippets - Method 1
<Example>:
orientation: 'vertical'
BoxLayout:
...
GridLayout: # left box
...
BoxLayout: # right box
...
BoxLayout: # footer
...
Method 2 - BoxLayout as root
This method replace the root widget with BoxLayout and realign the left box.
Snippets - Method 2
<Example>:
orientation: 'vertical'
AnchorLayout:
...
GridLayout: # left box
...
AnchorLayout: # right box
...
AnchorLayout: # footer
...
Method 3
This method add a BoxLayout as a child of the root, and the rest of the AnchorLayout as children of the BoxLayout.
Snippets - Method 3
<Example>:
anchor_x: "center"
anchor_y: "center"
BoxLayout:
orientation: 'vertical'
AnchorLayout:
...
GridLayout: # left box
...
AnchorLayout: # right box
...
AnchorLayout: # footer
...
Example
Method 1 - No AnchorLayouts
main.py
from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string("""
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint: 1, 0.75
GridLayout:
size_hint: 0.2, 1
canvas.before:
Color:
rgba: 1, 0, 0, 1
Rectangle:
size: self.size
pos: self.pos
cols: 3
row_force_default: True
row_default_height: 40
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
BoxLayout:
orientation: 'vertical'
canvas.before:
Color:
rgba: 0, 1, 0, 1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "HELLO..."
Label:
text: "WORLD..."
BoxLayout:
size_hint: 1, 0.25
canvas.before:
Color:
rgba: 0, 0, 1, 1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "FOOTER"
"""))
Output: Method 1 - No AnchorLayouts
Method 2 - BoxLayout as root
main.py
from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string("""
BoxLayout:
orientation: 'vertical'
AnchorLayout:
size_hint: 1, 0.75
anchor_x: 'left'
anchor_y: 'top'
GridLayout:
size_hint: 0.2, 1
canvas.before:
Color:
rgba: 1, 0, 0, 1
Rectangle:
size: self.size
pos: self.pos
cols: 3
row_force_default: True
row_default_height: 40
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
BoxLayout:
orientation: 'vertical'
size_hint: 0.8, 1
canvas.before:
Color:
rgba: 0, 1, 0, 1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "HELLO..."
Label:
text: "WORLD..."
AnchorLayout:
size_hint: 1, 0.25
anchor_x: 'left'
anchor_y: 'bottom'
canvas.before:
Color:
rgba: 0, 0, 1, 1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "FOOTER"
"""))
Output: Method 2 - BoxLayout as root
Changing the Example class to extend FloatLayout instead of AnchorLayout allows more control of its children. With that change to Example, here is a kv that looks more like what you want:
<Example>:
AnchorLayout:
anchor_x: "center"
anchor_y: "top"
size_hint: (0.2, 0.75)
pos_hint: {'x':0, 'top':1}
GridLayout:
cols: 3
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
AnchorLayout:
anchor_x: "center"
anchor_y: "top"
size_hint: (0.8, 0.75)
pos_hint: {'right':1, 'top':1}
BoxLayout:
orientation: "vertical"
Label:
text: "HELLO..."
Label:
text: "WORLD..."
AnchorLayout:
anchor_x: "center"
anchor_y: "bottom"
size_hint: (1, 0.25)
pos_hint: {'x':0, 'y':0}
Label:
text: "FOOTER"
So, i've been studying the kivy library for a couple of days and I did a simple app with some screens simulating a SignIn/Register enviroment. What i noticed is, in my .kv file, when I set "global parameters" to my widgets, the Button parameters are simply not changing. Take a look:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
Gerencia:
transition: FadeTransition()
TelaDeLogin:
TelaDeCadastro:
TelaEsqueci:
TelaEmDesenvolvimento:
<Button>:
size_hint: 1, 0.1
font_size: 40
color: 1, 1, 1, 1
<Label>:
size_hint: 0.5, 0.1
color: 1, 1, 0, 1
font_size: 40
<TextInput>:
multiline: False
size_hint: 0.5, 0.1
<TelaDeLogin>:
name: "Login"
FloatLayout:
Button:
on_release: app.root.current = "Desenvolvimento"
pos_hint: {'x':0, 'y':0.2}
text: 'Logar'
Button:
on_release: app.root.current = "Esqueci"
pos_hint: {'x':0, 'y':0.1}
text: 'Esqueci a senha'
Button:
on_release: app.root.current = "Cadastro"
pos_hint: {'x':0, 'y':0}
text: 'Cadastre-se'
Label:
text: "Usuário"
pos_hint: {'x':0.25, 'y':0.8}
TextInput:
pos_hint: {'x':0.25, 'y':0.7}
Label:
text: "Senha"
pos_hint: {'x':0.25, 'y':0.6}
TextInput:
password: True
pos_hint: {'x':0.25, 'y':0.5}
I'm ommiting some other screens but they are irrelevant, what happened was, I did some tests and changing the size_hint inside of "<"Button">" doesn't affect the size of my Buttons at all, they are apparently just getting some default size. Another weird thing that happened was, just to test, I did some changes to font_size both inside "<"Button">" and inside "<"Label">", and the value I put into Label also affected my Buttons on the screen, same happened with color. So it seems like my Buttons are getting their values from "<"Label">" and not from "<"Button>". Does anyone have any Idea what's going on?
Explanation
You have overwritten the base class Label, and Button is a Label as specified in the following Kivy documentation. In your Kivy App, Button has inherited the size_hint, font_size and color from your customized Label.
Button
The Button is a Label with associated actions that are triggered when
the button is pressed (or released after a click/touch). To configure
the button, the same properties (padding, font_size, etc) and sizing
system are used as for the Label class
Solution
Create dynamic classes for Label and Button.
Create a dynamic class with inheritance from Button. Replace instantied children, Button: with MyButton:
Create a dynamic class with inheritance from Label. Replace instantied children, Label: with MyLabel:
Snippets
<MyButton#Button>:
size_hint: 1, 0.1
font_size: 40
color: 1, 1, 1, 1
<MyLabel#Label>:
size_hint: 0.5, 0.1
color: 1, 1, 0, 1
font_size: 40
...
<TelaDeLogin>:
name: "Login"
FloatLayout:
MyButton:
on_release: app.root.current = "Desenvolvimento"
pos_hint: {'x':0, 'y':0.2}
text: 'Logar'
MyButton:
on_release: app.root.current = "Esqueci"
pos_hint: {'x':0, 'y':0.1}
text: 'Esqueci a senha'
MyButton:
on_release: app.root.current = "Cadastro"
pos_hint: {'x':0, 'y':0}
text: 'Cadastre-se'
MyLabel:
text: "Usuário"
pos_hint: {'x':0.25, 'y':0.8}
TextInput:
pos_hint: {'x':0.25, 'y':0.7}
MyLabel:
text: "Senha"
pos_hint: {'x':0.25, 'y':0.6}
TextInput:
password: True
pos_hint: {'x':0.25, 'y':0.5}
Output
Kivy 1.10.0 and using a kv file for my Kivy language.
Python 3.6
I have an app that works with mysql3. One page of the app allows me to add an 'flash card' to the database. One of the form elements when adding the flash card uses a Multiselect Spinner to add one or more tags, this data is then saved to the database. The first time I access this page, I can use the spinner and add everything as expected. Then if I go back to try to add a second flash card, even though the form is cleared and everything looks exactly as it does the first time I add a flash card, the spinner acts strangly. Data seems to be getting stored somewhere, as can be seen in the third gif, and somehow loaded back into the spinner data. (The problem is the same for the 'decks' spinner.)
This gif shows it working properly the first time I add a new card:
This gif shows the second time I add a new card (this happens regardless of what I do between adding the two cards, except quitting the app entirely):
This gif shows that data seems to be retained:
Because the code is long, I will add only what I believe relevant. If something is missing, please let me know and I'll add it right away.
class NewFlashCardScreen(Screen):
data = DictProperty({})
data_fc_tag_ids = DictProperty({})
data_fc_deck_ids = DictProperty({})
__events__ = ('on_submit',)
fc_tag_spinner_list = ListProperty(None)
fc_deck_spinner_list = ListProperty(None)
def on_parent(self, widget, parent):
gd = App.get_running_app()
self.fc_tag_spinner_list = []
fc_tag_list = Queries.get_fc_tag_list()
if len(fc_tag_list) > 0:
for fc_tag in fc_tag_list:
self.fc_tag_spinner_list.append(fc_tag[1])
self.data_fc_tag_ids[fc_tag[1]] = fc_tag[0]
else:
self.fc_tag_spinner_list.append("")
self.fc_deck_spinner_list = []
fc_deck_list = Queries.get_fc_deck_list()
if len(fc_deck_list) > 0:
for fc_deck in fc_deck_list:
self.fc_deck_spinner_list.append(fc_deck[1])
self.data_fc_deck_ids[fc_deck[1]] = fc_deck[0]
else:
self.fc_deck_spinner_list.append("")
def get_spinner_lists(self):
pass
def on_submit(self, data):
gd = App.get_running_app()
self.data['orig'] = gd.glob_dict['orig']
title = data['fc_title'] if data['fc_title'] else " "
front = data['fc_front'] if data['fc_front'] else " "
back = data['fc_back'] if data['fc_back'] else " "
difficulty = data['fc_difficulty'] if data['fc_difficulty'] else 0
self.fc_id = MiscFuns.get_id(16)
try:
c.execute("""
INSERT INTO `tbl_learning_flash_cards` (`fc_id`,`fc_title`,`fc_front`,`fc_back`,`fc_difficulty`)
VALUES (?,?,?,?,?)
""", (self.fc_id, title, front, back, difficulty))
conn.commit()
except sqlite3.Error as e:
print("An error occurred:", e.args[0])
class MultiSelectSpinner(Button):
dropdown = ObjectProperty(None)
values = ListProperty([])
selected_values = ListProperty([])
def __init__(self, **kwargs):
self.values.clear()
self.selected_values.clear()
self.bind(dropdown=self.update_dropdown)
self.bind(values=self.update_dropdown)
super(MultiSelectSpinner, self).__init__(**kwargs)
self.bind(on_release=self.toggle_dropdown)
def toggle_dropdown(self, *args):
if self.dropdown.parent:
self.dropdown.dismiss()
else:
self.dropdown.open(self)
def update_dropdown(self, *args):
if not self.dropdown:
self.dropdown = DropDown()
values = self.values
if values:
if self.dropdown.children:
self.dropdown.clear_widgets()
for value in values:
b = Factory.MultiSelectOption(text=value)
b.bind(state=self.select_value)
self.dropdown.add_widget(b)
def select_value(self, instance, value):
if value == 'down':
if instance.text not in self.selected_values:
self.selected_values.append(instance.text)
else:
if instance.text in self.selected_values:
self.selected_values.remove(instance.text)
def on_selected_values(self, instance, value):
if value:
self.text = ';'.join(value)
else:
self.text = ''
And the kv file:
<NewFlashCardScreen>:
BoxLayout:
orientation: "vertical"
BoxLayout:
size_hint_y: 0.1
Label:
size_hint_x: 0.2
text: "Card Title"
text_size: self.text_size
valign: 'middle'
TextInput:
id: new_fc_title
multiline: False
padding_y: [self.height / 2.0 - (self.line_height / 2.0) * len(self._lines), 0]
text: root.data['fc_title'] if 'fc_title' in root.data else ""
on_text: root.data['fc_title'] = self.text
Label:
size_hint_x: 0.2
text: "Difficulty"
text_size: self.text_size
valign: 'middle'
BoxLayout:
size_hint_y: 0.1
Label:
size_hint_x: 0.2
text: "Card Tag(s)"
text_size: self.text_size
valign: 'middle'
BoxLayout:
MultiSelectSpinner:
id: new_fc_tag
text: root.data['fc_tags'] if 'fc_tags' in root.data else "Select tag(s)"
values: root.fc_tag_spinner_list
on_text: root.data['fc_tags'] = self.text
Button:
size_hint_x: 0.3
text: "New Tag"
on_release: lib.Navigation.page_nav(dest='new_flash_card_tag', orig='new_flash_card', edit=False)
BoxLayout:
size_hint_x: 0.2
TextInput:
padding_y: [self.height / 2.0 - (self.line_height / 2.0) * len(self._lines), 0]
id: new_fc_difficulty
text: root.data['fc_difficulty'] if 'fc_difficulty' in root.data else "0"
on_text: root.data['fc_difficulty'] = self.text
BoxLayout:
size_hint_y: 0.1
Label:
size_hint_x: 0.2
text: "Card Deck(s)"
text_size: self.text_size
valign: 'middle'
BoxLayout:
MultiSelectSpinner:
id: new_fc_deck
text: root.data['fc_decks'] if 'fc_decks' in root.data else "Select deck(s)"
values: root.fc_deck_spinner_list
on_text: root.data['fc_decks'] = self.text
Button:
size_hint_x: 0.3
text: "New Deck"
on_release: lib.Navigation.page_nav(dest='new_flash_card_deck', orig='new_flash_card', edit=False)
BoxLayout:
size_hint_x: 0.2
BoxLayout:
orientation: "vertical"
Label:
size_hint_y: 0.1
text: "Card Front"
BoxLayout:
TextInput:
id: new_fc_front
multiline: True
text: root.data['fc_front'] if 'fc_front' in root.data else ""
on_text: root.data['fc_front'] = self.text
RstDocument:
text: new_fc_front.text
show_errors: True
BoxLayout:
orientation: "vertical"
Label:
size_hint_y: 0.1
text: "Card Back"
BoxLayout:
TextInput:
id: new_fc_back
multiline: True
text: root.data['fc_back'] if 'fc_back' in root.data else ""
on_text: root.data['fc_back'] = self.text
RstDocument:
text: new_fc_back.text
show_errors: True
BoxLayout:
size_hint_y: 0.2
Button:
text: "Cancel"
on_release: lib.Navigation.page_nav(dest='prev_page', orig='new_flash_card', edit=False)
Button:
text: "Submit"
on_release: root.dispatch('on_submit', root.data)
I've tried clearing the dictionary files, self.data, self.data_fc_tag_ids, and self.data_fc_deck_ids, but that doesn't help.
I have no idea what data is being retained and how to get rid of it. Thank you.
John Don't woory! I get the solution.. Here is the path: In kv file first we can mention Dropdown widget, under Drop down we will mention check boxes and this is the answer.. Here is the kv file code:
DropDown:
padding: 0, 0, 0, root.width * 0.4
id: dropdown
on_select: btn.text = '{}'.format(args[1])
GridLayout:
size_hint_y: None
height: 44
cols: 2
row_default_height: '10dp'
Label:
id: person
text: 'Person'
text_size: self.size
valign: 'middle'
CheckBox:
text: 'check me'
on_active:
root.on_checkbox_active(person.text, self.active)
GridLayout:
size_hint_y: None
height: 44
cols: 2
row_default_height: '10dp'
Label:
id: vehicle
text: 'Vehicle'
text_size: self.size
valign: 'middle'
CheckBox:
id: vecle
text: 'check me'
on_active:
root.on_checkbox_active(vehicle.text, self.active)
GridLayout:
size_hint_y: None
height: 44
cols: 2
row_default_height: '10dp'
Label:
id: aircraft
text: 'Air_craft'
text_size: self.size
valign: 'middle'
CheckBox:
text: 'check me'
on_active:
root.on_checkbox_active(aircraft.text, self.active)
The .py file:
class My_class(BoxLayout):
def on_checkbox_active(checkbox_ref, name, checkbox_value):
if checkbox_value:
print('', name, 'is active')
else:
print('', name, 'is inactive')
pass
I was trying to look at different examples online to solve this issue but Still cannot figure out. I have an app that calls a popup class. The popup has an input field that does some manipulation to the text in the input field. The manipulated data is stored in a variable inside of the popup class. Now how can the parent widget access the data obtained from this widget. Here is a short example of the code.
KV
<ScreenManagement>:
ScreenManager:
id: manager
size_hint_y: 93
Screen:
name: "Case_info_screen"
id: sc1
FloatLayout:
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: 10
canvas.before:
Color:
rgb: 0.17, 0.17, 0.17 # your color here
Rectangle:
pos: self.pos
size: self.size
Label:
text_size: self.size
font_size: 20
valign: 'middle'
height: "75dp"
size_hint_y: None
color: 1,1,1,1
size_hint_x: 75
text: " Case Info"
RelativeLayout:
size_hint_x: 25
Button:
text_size: self.size
halign: 'center'
valign: 'middle'
size_hint: 0.70, 0.6
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
text: 'Automatic Filler'
on_press: root.formfiller()
BoxLayout:
size_hint_y: 5
spacing: 35
LabelCases:
text: ' Name: '
width: '125dp'
size_hint_x: None
TextInput:
id: first_name_input
width: '300dp'
height: '40dp'
size_hint_x: None
font_size: 18
hint_text: 'First Name'
TextInput:
id: last_name_input
width: '300dp'
height: '40dp'
size_hint_x: None
font_size: 18
hint_text: 'Last Name'
<Formfillerpop>:
title: 'Automatic Filler'
size_hint: None, None
size: 600, 600
BoxLayout:
orientation: 'vertical'
Label:
size_hint_y: 20
text: 'Please Paste your text'
markup: True
TextInput:
id: sentence
size_hint_y: 65
BoxLayout:
size_hint_y: 10
orientation: 'horizontal'
Button:
text: 'Analyze'
on_press: root.on_analyze(sentence.text)
Button:
text: 'Close'
on_press: root.closepop()
Python:
class Formfillerpop(Popup):
selection = StringProperty
id = ObjectProperty
def on_analyze(self, selection):
analyze = TextExtractor(selection)
names = analyze.name()
def closepop(self):
self.dismiss()
class ScreenManagement(FloatLayout):
def formfiller(self, *args):
Formfillerpop().open()
class IOApp(App):
def build(self):
return ScreenManagement()
if __name__ == '__main__':
IOApp().run()
Ultimately I want to take the txt from names in the popup and then autopopulate the first name and last name in the main app with the analyzed data
Sorry if this is basic. I am fairly new to Kivy.
You can access popup content using its content property. You can use it to read text property of read underlying TextInput. For example this code binds this property to local popup_text StringProperty, which means that any change in the popup text input will be reflected there:
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
Builder.load_string('''
<CustomPopup>:
size_hint: .5, .5
auto_dismiss: False
title: 'Hello world'
BoxLayout:
text_input: text_input
orientation: 'vertical'
TextInput:
id: text_input
Button:
text: 'dismiss'
on_press: root.dismiss()
''')
class CustomPopup(Popup):
pass
class TestApp(App):
popup_text = StringProperty()
def build(self):
l = BoxLayout()
l.add_widget(Button(
text='show_popup', on_press=self.show_popup
))
l.add_widget(Button(
text='print popup text', on_press=self.print_popup_text
))
return l
def show_popup(self, *args):
p = CustomPopup()
p.content.text_input.bind(text=self.setter('popup_text'))
p.open()
def print_popup_text(self, *args):
print(self.popup_text)
if __name__ == '__main__':
TestApp().run()
I am using pydev on eclipse luna. My kv file is as follows:
<LoginForm>:
userid: userid
password: password
size_hint_x: 0.5
size_hint_y: None
height: 200
orientation: 'vertical'
pos_hint: {'center_x': 0.5,'center_y':0.5}
minimum_height: 100
minimum_width: 100
#User ID
Label:
text: 'User ID'
font_size: 20
size_hint_x: None
TextInput:
id: userid
font_size: 20
#User PW
Label:
text: 'Password'
font_size: 20
TextInput:
id: password
password: True
font_size: 20
Button:
text: 'Login'
My python code is:
from kivy.app import App;
from forms.login import LoginForm;
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
class LoginForm(BoxLayout):
def __init__(self, **kwargs):
super(LoginForm, self).__init__(**kwargs)
class StartApp(App):
def build(self):
Window.size = (480, 800)
return LoginForm()
#return StartApp();
if __name__ == '__main__':
StartApp().run()
Output:
The code is working correctly, however, my issue is that there is still some gap at left which is not present for other controls. I want User ID to be completely left aligned (in the above pic it is left aligned, but some space is still left).
Could you please advice/correct me on where I went wrong?
The Label isn't left-aligned because you haven't actually set that, by disabling the size_hint_x it just takes the default width of 100 pixels and the text appears in its centre.
You have two options for declaring the label.
Label:
text: 'User ID'
font_size: 20
size_hint_x: None
width: self.texture_size[0]
This will set the width of the Label to the exact size of the texture containing the image of the text. However, I think it's probably preferable to do the following:
Label:
text: 'User ID'
font_size: 20
text_size: self.size
halign: 'left'
valign: 'middle'
This way, rather than messing with the widget size/position you set the text_size (this controls the bounding box of the text texture) and the built in text alignment options take care of the rest.
In this case, the results of these should be similar if not identical.