Pull value from Kivy Spinner - spinner

We have a spinner in our code and need to assign a value to the selection so we can use it later.
GridLayout:
cols: 2
Label:
font_size: '48sp'
text: "[color=000000][sub]Select a sport:[/sub][/color]"
halign: 'left'
valign: 'middle'
markup: True
text_size: self.size
Spinner:
text: 'Select a sport'
values: ('Soccer', 'Basketball', 'Volleyball', 'Handball')
size: (100,44)

The spinner gives several options that, when selected, will replace its text. So if you select 'Basketball', its text property will be 'Basketball'. You can access the value this way.

Related

Kivy - How to Size Embedded Anchor Layouts?

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"

python kivy : How to make switch Button work with carousel

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.

Kivy Button changing values unwantedly (size_hint)

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 using markup for two different text sizes in a single button not working

I'm in the process of converting an application from pure Python, to using kivy for screen handling. I'm a kivy newbie!
I'm attempting to replicate a screen which displays current date and time, on two lines, with different sizes for the two lines. I use two different [size=?] markups in the string to be displayed, but the two lines are always displayed at the same size (the second size specified) - how can I get them to be different sizes?
I have seen suggestions that this could be achieved using html, but fear that would be horribly inefficient.
Code is:
<C>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
Button:
text:
'[size=48]' + app.date + '[/size]' + \
'\n[size=96]' + app.time + '[/size]'
background_color: (0, 0, 0, 0)
halign: 'center'
markup: True
on_press: app.stop()
Status:
id: stat
I used your code and the lines had a different font size. Therefore the problem must be outside of the code you provided.
py:
from kivy.app import App
from kivy.properties import StringProperty
class MyApp(App):
date = StringProperty('2017-09-30')
time = StringProperty('Now')
if __name__ == '__main__':
MyApp().run()
kv:
BoxLayout:
orientation: 'vertical'
BoxLayout:
Button:
text:
'[size=48]' + app.date + '[/size]' + \
'\n[size=200]' + app.time + '[/size]'
background_color: (0, 0, 0, 0)
halign: 'center'
markup: True
on_press: app.stop()
Alternatively, you can use the following kv-file:
Button:
on_press: app.stop()
BoxLayout:
pos: self.parent.pos
size: self.parent.size
orientation: 'vertical'
Label:
text: app.date
font_size: 48
Label:
text: app.time
font_size: 96
To generate sth which also behaves more like a button in kv, changes the background on press.

Label not aligned correctly

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.

Resources