Are Kivy Layouts Essentially Widgets? - python

I have a kivy app that I am (learning) to write. I am a bit confused about the layouts and when to use which ones.
I have a base class in a .kv file that then contains a number of layouts. Eventually these components will talk to each other and will be dynamically generated, but the first thing I wanted to do was just to get all the components on a screen to see if I could.
In a structure like this:
<MyApp>
<AnchorLayout>
<Widget1>
<Widget2>
<FloatLayout>
<Widget3>
<Widget4>
<Label>
text: "text here"
where is the proper place to use the size_hint and pos_hint tags. Should it be at the widget level, or the layout level? If anyone can be bothered, the reason I am asking this is that in the following code, it seems that for the Label at the end, I have to position it manually, the pos_hint does nothing (I want it more or less 25% up the page on the left hand side). What am I missing?
# File name: MagStripeApp.kv
#:kivy 1.9.0
<MagStripeReader>:
AnchorLayout:
anchor_x: 'left'
anchor_y: 'top'
HeaderBar:
id: _header_bar
size_hint: 1, 0.15
AnchorLayout:
anchor_x: 'center'
anchor_y: 'bottom'
SessionBar:
id: _session_bar
mag_stripe_reader: root
entry_box: _entry_box
size_hint: 1, 0.1
pos_hint: {'center_x':0.5, 'center_y': 0.5}
FloatLayout:
size_hint: 1, 0.2
EntryBox:
id: _entry_box
request_box: _request_box
person_counter: _person_counter
request_box: _request_box
size_hint: 0.333, 1
RequestBox:
id: _request_box
person_counter: _person_counter
card_reader: _card_reader
size_hint: 0.333, 1
CardReader:
id: _card_reader
person_counter: _person_counter
size_hint: 0.333, 1
PersonCounter:
id: _person_counter
<HeaderBar#Label>:
text: "Mag Stripe Reader Application"
font_size: root.height/2.5
size: self.texture_size
bold: True
color: 0, 0.70, 0.93, 1
#This is not quite right, but is ok for now. The resizing does not work
#quite perfectly.
<SessionButton#ToggleButton>:
group: 'session_options'
background_color: 0, 0.70, 0.93, 1
color: 0.11, 0.39, 0.33, 0.75, 0.02
bold: True
<SessionBar#GridLayout>:
cols: 2
#col_default_width: root.width/3
SessionButton:
text: "Start Session"
SessionButton:
text: "End Session"
<EntryButton#Button>:
group: 'entry_buttons'
background_color: 0, 0.70, 0.93, 1
color: 0.11, 0.39, 0.33, 0.75, 0.02
bold: True
<EntryBox#GridLayout>:
pos_hint: {'x':0, 'center_y':0.5}
cols: 1
rows: 2
Label:
text: "Does Entrant have an EBT card?"
font_size: root.height/8
size: self.texture_size
bold: True
color: 0, 0.70, 0.93, 1
GridLayout:
cols: 2
EntryButton:
text: 'YES'
EntryButton:
text: 'NO'
<RequestButton#Button>:
group: 'request_buttons'
background_color: 0, 0.70, 0.93, 1
color: 0.11, 0.39, 0.33, 0.75, 0.02
bold: True
<RequestBox#GridLayout>:
cols: 1
rows: 2
pos_hint: {'x': 0.333, 'center_y':0.5}
Label:
text: "Will Entrant scan EBT card?"
font_size: root.height/8
size: self.texture_size
bold: True
color: 0, 0.70, 0.93, 1
GridLayout:
cols: 2
EntryButton:
text: 'YES'
EntryButton:
text: 'NO'
<CardReader#GridLayout>
cols: 1
rows: 2
pos_hint: {'x': 0.666, 'center_y':0.5}
Label:
text: 'Please scan EBT card'
font_size: root.height/8
size: self.texture_size
bold: True
color: 0, 0.70, 0.93, 1
TextInput:
password: True
multiline: False
<PersonCounter#Label>:
id: _person_counter
text: '1'
pos_hint: {'x' : 0.1, 'y' : 0.25}
#pos: -500, 100
size: self.texture_size
halign: 'left'
font_size: 50

Are Kivy Layouts Essentially Widgets?
Layouts are widgets. The declaration of the Layout class is class Layout(Widget): etc.
where is the proper place to use the size_hint and pos_hint tags. Should it be at the widget level, or the layout level?
It should be one level below whatever widget you're trying to set their value for. e.g.
BoxLayout:
orientation: 'vertical' # this applies to the BoxLayout instance
FloatLayout:
size_hint_y: 0.75 # The FloatLayout will take 75% of the vertical space
Label:
pos_hint: {x: '0.5', y: '0.75'} # The Label is placed 50% across the x axis, and 75% up the y axis
size_hint: None, None
size: 50, 50 # ...and has a fixed size
text: '!'
Button:
size_hint_y: 0.25
I can't comment on your specific example with a Label, because it's not valid kv and doesn't try to do the thing you says fails. If this doesn't answer things for you, provide a full example that doesn't do what you expect.

Related

Size_hint is doing weird things and being very inconsistent

I've created 4 "indicator buttons" and I've given all of them the same size_hint values, but they don't have the same size when I launch the program. Additionally I've created "validate buttons" (which also share the same size_hint values) and again, when I launch the program, they don't have the same size.
Did I miss something? How exactly does size_hint work? (the indicator buttons are the large squares on the top right corner of the picture)
#indicators for the 1st row of buttons
Button:
id: i11
pos_hint: {"x": 0.2, "y": 0.7}
size_hint: 0.05, 0.065
background_normal: ""
background_color: root.colori11
Button:
id: i12
pos_hint: {"x": 0.18, "y": 0.7}
size_hint: 0.05, 0.065
background_normal: ""
background_color: root.colori12
Button:
id: i13
pos_hint: {"x": 0.16, "y": 0.7}
size_hint: 0.05, 0.065
background_normal: ""
background_color: root.colori13
Button:
id: i14
pos_hint: {"x": 0.14, "y": 0.7}
size_hint: 0.05, 0.065
background_normal: ""
background_color: root.colori14
#validate button
Button:
pos_hint: {"x": 0.66, "y": 0.725}
size_hint: 0.05, 0.065
text: "V"
on_release:
root.btn_action_v2()
picture of my program
I've done several Kivy layouts and have never once used pos_hint so my suggestion is to comment those away and see what result you get.
size_hint is a relative and so I have always used integers as I find those a bit easier to work with. Furthermore you have the option to use size_hint_x or size_hint_y individually

Add Toggle Buttons with if statement

Based on an input (0, 1, 2 or 3) the kv.file or py.file should add a group of Toggle Buttons to the already existing layout. I tried a lot but can't seem to figure it out and would love some advice, since it is all still a bit new to me.
So when self.reminder() = 0, no Toggle Buttons are shown.
When self.reminder() = 1, one group of Toggle Buttons is shown.
When self.reminder() = 2, two groups of Toggle Buttons are shown.
When self.reminder() = 3, three groups of Toggle Buttons are shown.
self.reminder() will not excess the value of 3.
So I have got my .py file
import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
import csv
from kivy.core.window import Window
class WindowManager(ScreenManager):
pass
#Backgroundcolour
Window.clearcolor = (0.67, 0.83, 0.88, 1)
class DiaryToday(Screen):
user_id = 3
# reads how many reminders (aka Toggle Buttons) the user wants from csv file
# used for textlabel, this textlabel will not show if reminder == 0 (is stated in kv file)
def reminder(self):
with open('users.csv') as file: #TO DO: needs to be adjusted to global ID
reader = csv.DictReader(file)
for row in reader:
if row['id'] == str(self.user_id): #TO DO: needs to be adjusted to global ID
if row['mood_rem'] == 'Zero':
return(0)
else:
return(row['mood_rem'][0])
# TO DO: STORES in CSV file which emoji you clicked
def mood_value(self, mood):
print (mood)
#Takes care of which group of ToggleButtons is shown in the Diary Screen
def add(self):
if root.reminder() == 0:
#should add or show no Toggle Buttons
if root.reminder() == 1:
#should add or show 1 set of Toggle Buttons
if root.reminder() == 2:
#should add or show 2 sets of Toggle Buttons
if root.reminder()== 3:
#should add or show 3 sets of Toggle Buttons
class LoopApp(App):
def build(self):
return DiaryToday()
if __name__ == '__main__':
LoopApp().run()
And my .kv file
<DiaryToday>:
name: "diarytoday"
answer: answer
diaryinput: diaryinput
id: test
FloatLayout:
Button:
background_color: 0.1, 0.5, 0.6, 1
pos_hint:{'center_y':0.05, 'center_x': 0.5}
font_size: 18
size_hint: 0.1, 0.05
text: "Save"
Button:
pos_hint:{'center_y':0.95, 'center_x': 0.175}
background_color: 0.1, 0.5, 0.6, 1
font_size: 18
size_hint: 0.15, 0.05
text: "Previous day"
Label:
pos_hint:{'center_y':0.95, 'center_x': 0.5}
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
text: 'date'
font_size: 22
Label:
pos_hint:{'center_y':0.87, 'center_x': 0.5}
font_size: 18
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
text: 'Question'
TextInput:
font_size: 14
size_hint: 0.8, 0.1
pos_hint:{'center_y':0.78, 'center_x': 0.5}
id: answer
Label:
pos_hint:{'center_y':0.67, 'center_x': 0.5}
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
font_size: 18
text: 'My Diary'
TextInput:
font_size: 14
size_hint: 0.8, 0.22
pos_hint:{'center_y':0.51, 'center_x': 0.5}
id: diaryinput
Label:
pos_hint:{'center_y':0.36, 'center_x': 0.5}
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
font_size: 18
text: ' ' if root.reminder() == 0 else 'How are you feeling?'
BoxLayout:
id: ToggleButtonGroup1
pos_hint: {'center_y':0.26, 'center_x': 0.5}
size_hint: 0.5, 0.1
ToggleButton:
background_normal: 'VerysadEmoji1.png'
background_down: 'VerysadEmoji2.png'
group: "emojis"
size_hint: 0.5, 1.3
on_press: root.mood_value(1)
ToggleButton:
background_normal: 'SadEmoji1.png'
background_down: 'SadEmoji2.png'
group: "emojis"
size_hint: 0.5, 1.3
on_press: root.mood_value(2)
ToggleButton:
background_normal: 'MediumEmoji1.png'
background_down: 'MediumEmoji2.png'
group: "emojis"
size_hint: 0.5, 1.3
on_press: root.mood_value(3)
ToggleButton:
background_normal: 'HappyEmoji1.png'
background_down: 'HappyEmoji2.png'
group: "emojis"
size_hint: 0.5, 1.3
on_press: root.mood_value(4)
ToggleButton:
background_normal: 'VeryHappyEmoji1.png'
background_down: 'VeryHappyEmoji2.png'
group: "emojis"
size_hint: 0.5, 1.3
on_press: root.mood_value(5)
Label:
pos_hint:{'center_y':0.19, 'center_x': 0.5}
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
font_size: 18
text: "Here will come Toggle Button Group 2"
Label:
pos_hint:{'center_y':0.12, 'center_x': 0.5}
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
font_size: 18
text: "Here will come Toggle Button Group 3"
Thanks!
You can define a class that is the Toggle Button Group that you want to add. Something like this:
class SomeToggles(BoxLayout):
group = StringProperty('') # this will be the group for the ToggleButtons
Then the add() method can be:
#Takes care of which group of ToggleButtons is shown in the Diary Screen
def add(self):
if self.reminder() == 0:
print('0')
#should add or show no Toggle Buttons
if self.reminder() == 1:
print('1')
self.ids.toggles.add_widget(SomeToggles(group=str(self.grp_count)))
self.grp_count += 1
#should add or show 1 set of Toggle Buttons
if self.reminder() == 2:
print('2')
#should add or show 2 sets of Toggle Buttons
if self.reminder()== 3:
print('3')
#should add or show 3 sets of Toggle Buttons
The above only handles the case where self.reminder() returns 1, but the others would be similar. Of course, the grp_count (which is just a construct of mine to define the group property) needs to be added:
class DiaryToday(Screen):
grp_count = 0
For this to work, a container with id of toggles must be defined. This will be another BoxLayout that contains the first set of Toggle Buttons as well as the added ones. So the modified kv file looks like:
<DiaryToday>:
name: "diarytoday"
answer: answer
diaryinput: diaryinput
id: test
FloatLayout:
Button:
background_color: 0.1, 0.5, 0.6, 1
pos_hint:{'center_y':0.05, 'center_x': 0.5}
font_size: 18
size_hint: 0.1, 0.05
text: "Save"
Button:
pos_hint:{'center_y':0.95, 'center_x': 0.175}
background_color: 0.1, 0.5, 0.6, 1
font_size: 18
size_hint: 0.15, 0.05
text: "Previous day"
Label:
pos_hint:{'center_y':0.95, 'center_x': 0.5}
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
text: 'date'
font_size: 22
Label:
pos_hint:{'center_y':0.87, 'center_x': 0.5}
font_size: 18
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
text: 'Question'
TextInput:
font_size: 14
size_hint: 0.8, 0.1
pos_hint:{'center_y':0.78, 'center_x': 0.5}
id: answer
Label:
pos_hint:{'center_y':0.67, 'center_x': 0.5}
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
font_size: 18
text: 'My Diary'
TextInput:
font_size: 14
size_hint: 0.8, 0.22
pos_hint:{'center_y':0.51, 'center_x': 0.5}
id: diaryinput
Label:
pos_hint:{'center_y':0.36, 'center_x': 0.5}
size_hint: 0.1, 0.05
color: 0.1, 0.5, 0.6, 1
font_size: 18
text: ' ' if root.reminder() == 0 else 'How are you feeling?'
BoxLayout: # this contains all the Toggle Button groups
id: toggles
orientation: 'vertical'
pos_hint: {'center_y':0.26, 'center_x': 0.5}
size_hint_y: None
height: self.minimum_height
BoxLayout:
id: ToggleButtonGroup1
pos_hint: {'center_y':0.26, 'center_x': 0.5}
size_hint: 0.5, None
height: self.minimum_height
ToggleButton:
background_normal: 'VerysadEmoji1.png'
background_down: 'VerysadEmoji2.png'
group: "emojis"
size_hint: 0.5, None
height: 40
on_press: root.mood_value(1)
ToggleButton:
background_normal: 'SadEmoji1.png'
background_down: 'SadEmoji2.png'
group: "emojis"
size_hint: 0.5, None
height: 40
on_press: root.mood_value(2)
ToggleButton:
background_normal: 'MediumEmoji1.png'
background_down: 'MediumEmoji2.png'
group: "emojis"
size_hint: 0.5, None
height: 40
on_press: root.mood_value(3)
ToggleButton:
background_normal: 'HappyEmoji1.png'
background_down: 'HappyEmoji2.png'
group: "emojis"
size_hint: 0.5, None
height: 40
on_press: root.mood_value(4)
ToggleButton:
background_normal: 'VeryHappyEmoji1.png'
background_down: 'VeryHappyEmoji2.png'
group: "emojis"
size_hint: 0.5, None
height: 40
on_press: root.mood_value(5)
<SomeToggles>:
pos_hint: {'center_y':0.26, 'center_x': 0.5}
size_hint: 0.5, None
height: self.minimum_height
ToggleButton:
group: root.group
size_hint: 0.5, None
height: 40
ToggleButton:
group: root.group
size_hint: 0.5, None
height: 40
ToggleButton:
group: root.group
size_hint: 0.5, None
height: 40
The above kv also includes the <SomeToggles> rule that defines how the new Toggle Button group is built. You will also need to provide a mechanism for calling self.reminder(). I just added that call to the mood_value() method.

Kivy anchor two widget at each side

I'm trying to do a video on top of a graph, with two buttons controlling the graph. I'd like one button to be at the left of the window, the other one at the right, both on the same row, and my problem is placing the - and + buttons.
I have the following kv file, the concerned buttons are the two Control class:
#:kivy 1.0.9
<Control>
canvas:
Rectangle:
size: 5, 5
pos: self.pos
<VideoWidget>:
video_player: video_handler
graph: graph_handler
data_plus: ctr_plus_handler
data_minus: ctr_minus_handler
BoxLayout:
orientation: 'vertical'
VideoHandler:
id: video_handler
state: 'play'
options: {'allow_stretch': True}
size_hint: 1, 0.45
on_touch_down: root.test()
on_position: root.move()
BoxLayout:
size_hint: 1, 0.1
orientation: 'horizontal'
Control:
id: ctr_minus_handler
size_hint: 0.1, 1
pos_hint: {'left': 0.1}
Control:
id: ctr_plus_handler
size_hint: 0.1, 1
pos_hint: {'right': 0.1}
GraphWidget:
id: graph_handler
size_hint: 1, 0.45
But both Control are taking half the width of the row, whatever I change... Any ideas ?
You can use an empty Widget to fill the blank space between the Controls like this:
BoxLayout:
size_hint: 1, 0.1
orientation: 'horizontal'
Control:
id: ctr_minus_handler
size_hint: 0.1, 1
Widget:
size_hint: 0.8, 1
Control:
id: ctr_plus_handler
size_hint: 0.1, 1
You have to use FloatLayout instead of BoxLayout with correct pos_hint values. Below is the snippet for the button widget part:
FloatLayout:
size_hint: 1, 0.1
orientation: 'horizontal'
Control:
id: ctr_minus_handler
size_hint: 0.1, 1
pos_hint: {'left': 1}
Control:
id: ctr_plus_handler
size_hint: 0.1, 1
pos_hint: {'right': 1}
Hope this would solve your issue.

Kivy Changing State of Toggle Button When Another Toggle Button Is Active

I have two toggle buttons. When one is in the "down" state I need the other one to be in the "normal" state. I tried making an if statement but it makes both buttons have the same state at the same time. Here it is:
on_state: exlexport.state = "down" if exlexport.state == "normal" else "normal"
Here is my full code:
<SettingsWindow>:
name:"settings"
FloatLayout:
Widget:
canvas.before:
# Background
Rectangle:
pos: self.pos
size: self.size
source: "Images/logo_br.png"
# Brothers Menu
Color:
rgba: 1,1,1,.3
Rectangle:
size: 200, 500
pos: self.width/10, self.height/7
Color:
rgba: 0,0,0,.5
Rectangle:
size: 190, 350
pos: self.width/9.4, self.height/3
# Jobs Menu
Color:
rgba: 1,1,1,.3
Rectangle:
size: 200, 500
pos: self.width/2.5, self.height/7
Color:
rgba: 0,0,0,.5
Rectangle:
size: 190, 350
pos: self.width/2.465, self.height/3
# Export Menu
Color:
rgba: 1,1,1,.3
Rectangle:
size: 200, 250
pos: self.width/1.43, self.height/3.08
Color:
rgba: 0,0,0,.5
Rectangle:
size: 190, 205
pos: self.width/1.416, self.height/3
# Brothers Scroll List
ScrollView:
size_hint: (None, None)
size: (150, 325)
pos_hint: {'center_x': .23, 'center_y': .62}
# Brothers Menu Scroll Label
Label:
size_hint: None, None
size: self.texture_size
text: root.pretty_list_people
# Jobs Menu Scroll Label
ScrollView:
size_hint: (None, None)
size: (150, 325)
pos_hint: {'center_x': .53, 'center_y': .62}
Label:
size_hint: None, None
size: self.texture_size
text: root.pretty_list_jobs
Button:
text:"Back"
size_hint: 0.1, 0.1
pos_hint: {"x":0, "y":0}
background_color: 1,1,1,.6
on_release:
app.root.current = "main"
root.manager.transition.direction = 'right'
# Brothers Title
Label:
text: "Brothers"
font_size: 30
italic: True
pos_hint: {"x":-0.275, "y":0.45}
color: 0,0,0,1
# Jobs Title
Label:
text: "Jobs"
font_size: 30
italic: True
pos_hint: {"x":0.02, "y":0.45}
color: 0,0,0,1
# Exporting Title
Label:
text: "Exporting"
font_size: 30
italic: True
pos_hint: {"x":0.325, "y":0.21}
color: 0,0,0,1
# Brothers Menu Buttons
Button:
text:"Update"
size_hint: 0.25, 0.1
pos_hint: {"x":0.1, "y":0.144}
on_press: root.Pretty_Print_People(root.get_People())
Button:
text:"Add"
size_hint: 0.125, 0.09
pos_hint: {"x":0.1, "y":0.243}
on_press: root.showpop_addbro()
Button:
text:"Remove"
size_hint: 0.125, 0.09
pos_hint: {"x":0.225, "y":0.243}
on_press: root.showpop_removebro()
Button:
text:"Update"
size_hint: 0.25, 0.1
pos_hint: {"x":0.1, "y":0.144}
on_press: root.Pretty_Print_People(root.get_People())
# Jobs Menu Buttons
Button:
text:"Add"
size_hint: 0.125, 0.09
pos_hint: {"x":0.4, "y":0.243}
on_press: root.showpop_addjob()
Button:
text:"Remove"
size_hint: 0.125, 0.09
pos_hint: {"x":0.525, "y":0.243}
on_press: root.showpop_removejob()
Button:
text: "Update"
size_hint: 0.25, 0.1
pos_hint: {"x":0.4, "y":0.144}
on_press: root.Pretty_Print_Jobs(root.get_Jobs())
# Exporting Menu Content
ToggleButton:
id: txtexport
text: "Toggle Text File Export"
size_hint: 0.236, 0.08
pos_hint: {"x":0.707, "y":0.59}
on_state: exlexport.state = "down" if exlexport.state == "normal" else "normal"
ToggleButton:
id: exlexport
text: "Toggle Excel File Export"
size_hint: 0.236, 0.08
pos_hint: {"x":0.707, "y":0.51}
The toggle buttons start after the comment "Exporting Menu Content"
ToggleButton:
id: txtexport
group: 'exportopts'
text: "Toggle Text File Export"
size_hint: 0.236, 0.08
pos_hint: {"x":0.707, "y":0.59}
state: 'down'
ToggleButton:
id: exlexport
group: 'exportopts'
text: "Toggle Excel File Export"
size_hint: 0.236, 0.08
pos_hint: {"x":0.707, "y":0.51}
Credit to this solution goes to John Anderson! Thank you.
Just assign the toggle buttons the same group via group property and set the state of one them to 'down'.
I was looking for a way to always make one of my toggle buttons be "down" because belonging to the same group, don't assure me that, they can both be "normal". In order to get that result and have always one button "down", I've added this line on each one:
on_press: self.state = "down"

How do I position widgets and use layouts in Kivy?

This: (https://imgur.com/a/Y9Xwl) (can't format it for some reason) is the user interface I am currently trying to create in Kivy. I am having difficulty recreating this as I do not understand the layout system and I have read a lot of documentation, watched a lot of Youtube videos, tinkered with the code and still I cannot get the desired result. So far this is my code, it has all the widgets that I need within it, they're just not sized/positioned how I want them:
from kivy.app import App
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.properties import ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class CaloriesScreen(Screen):
pass
class categoriesScreen(Screen):
pass
class loginScreen(Screen):
pass
class registerScreen(Screen):
pass
class shoppingListScreen(Screen):
pass
class theScreenManager(ScreenManager):
pass
root_widget = Builder.load_string('''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
theScreenManager:
transition: FadeTransition()
CaloriesScreen:
<CaloriesScreen>:
name: 'calories'
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'horizontal'
size_hint: 1, .3
Button:
text: '<'
size_hint: .1, 1
font_size: 75
background_normal: ""
background_color: 0.18, .5, .92, 1
on_release: app.root.current = 'main'
Label:
text: 'Calories'
halign: 'left'
font_size: 50
canvas.before:
Color:
rgb: 0.18, .5, .92
Rectangle:
pos: self.pos
size: self.size
Widget:
size_hint: .1, 1
canvas.before:
Color:
rgb: 0.18, .5, .92
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'horizontal'
size_hint: 1, .4
canvas.before:
Color:
rgb: 0.8, 0.8, 0.8
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'Recipes'
font_size: 30
color: 0.18, .5, .92, 1
size_hint: 1, 1
Button:
id: btn
text: 'Select a recipe...'
on_release: dropdown.open(self)
height: '48dp'
size_hint: .5, .3
pos: self.x, .3
DropDown:
id: dropdown
on_parent: self.dismiss()
on_select: btn.text = '{}'.format(args[1])
Button:
text: 'First recipe'
size_hint_y: None
height: '48dp'
on_release: dropdown.select('First Item')
Button:
text: 'Second recipe'
size_hint_y: None
height: '48dp'
on_release: dropdown.select('Second Item')
Button:
text: 'Third recipe'
size_hint_y: None
height: '48dp'
on_release: dropdown.select('Third Item')
Button:
text: '+'
font_size: 30
background_normal: ""
background_color: 0.18, .5, .92, 1
#on_release:
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'horizontal'
Label:
text: 'Food'
font_size: 30
color: 0.18, .5, .92, 1
Label:
text: 'Cal'
font_size: 30
color: 0.18, .5, .92, 1
BoxLayout:
orientation: 'horizontal'
Label:
text: 'Simple Cheese Omelette'
font_size: 30
color: 0.18, .5, .92, 1
Label:
text: '241'
font_size: 30
color: 0.18, .5, .92, 1
BoxLayout:
orientation: 'horizontal'
Label:
text: 'Burger'
font_size: 30
color: 0.18, .5, .92, 1
Label:
text: '295'
font_size: 30
color: 0.18, .5, .92, 1
BoxLayout:
orientation: 'horizontal'
Label:
text: 'Tomato and caper linguine '
font_size: 30
color: 0.18, .5, .92, 1
Label:
text: '393'
font_size: 30
color: 0.18, .5, .92, 1
BoxLayout:
orientation: 'vertical'
canvas.before:
Color:
rgb: 0.8, 0.8, 0.8
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'horizontal'
Label:
text: 'Total Cal'
font_size: 30
color: 0.18, .5, .92, 1
Label:
text: '929'
font_size: 30
color: 0.18, .5, .92, 1
BoxLayout:
orientation: 'horizontal'
Label:
text: 'You are under calories'
font_size: 30
color: 0.18, .5, .92, 1
Button:
text: 'Clear'
font_size: 75
background_normal: ""
background_color: 0.18, .5, .92, 1
#on_release:
''')
class RecipeApp(App):
def build(self):
return root_widget
if __name__ == "__main__":
RecipeApp().run()
This(https://imgur.com/a/zW2z0) (can't format it for some reason) is what the output of that code looks like. The top bar with the "<" button is how I want it and I've only tried to edit the horizontal row of widgets below it. I cannot position the dropdown menu with the 'select your recipe' label how I would like it. I have tried altering it's y-axis multiple times but it always sinks to the botton of the boxlayout. I even tried giving it a new boxlayout just for the dropdown and tried doing: pos: self.parent.x, self.parent.y * 0.5 assuming it would go halfway up the y-axis of it's parent layout (the boxlayout) but still nothing. I am wondering whether it would be better to just use a floatlayout and manually position all the widgets but I am unsure how this will work well when I compile it into an APK for an Android device. What is the best way to go about positioning my widgets on the screen?
Use pos_hint for this.
If pos_hint: {'top': 1}, the top of the widget will hit the roof of the parent box.
So if your widgets height is 30% of its parent box (size_hint: 0.5, 0.3), and you want it to be centered vertically, you want pos_hint: {'top': 0.5 + 0.3/2}, which means the top of the widget will be half way to the roof + half of the widgets height which is 15% of the parent box.
That takes us 65% to the top :)
size_hint: 0.5, 0.3
pos_hint: { 'top' : 0.65}
If the widgets size_hint is dynamic you can do something like this.
pos_hint: {'top': 0.5 + self.size_hint[1]/2}
And lets take your Select recipe button as an example:
Button:
id: btn
text: 'Select a recipe...'
on_release: dropdown.open(self)
height: '48dp'
size_hint: .5, .3
pos_hint: {'top': 0.5 + self.size_hint[1]/2}

Categories

Resources