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
Related
I have a problem that I don't know what command to use to prevent text from going outside the window
Label:
color: (0,1,0,1)
size_hint: (None,None)
pos_hint: {'y': 0.75, 'x': 0.2}
center: self.center
Button:
text: "Powrót"
font_size: 32
pos_hint: {'center_x': .5}
size_hint: (1, 0.1)
on_release: app.root.current = "first"
Thank you in advance for any advice
See the documentation. Try adding:
size: self.texture_size
to the Label.
So I am making a notes app as a part of a bigger app. What I want is that every time before the user enters the screen, all the existing notes will be fetched from MongoDB and displayed.
Initially, I tried it with just a on_pre_enter event but then every time the I went to a different screen and came back, the last note from the database got written again on top of the existing labels.
So, then I added a on_pre_leave function but now what happens is that the first time, notes get displayed. But if you leave and come back, the whole screen is empty.
Any suggestions would be appreciated.
Current code:
class Reminders(Screen):
collection = db['Notes']
def on_pre_enter(self, *args):
records = self.collection.find({})
for record in records:
existing_lbl = Label(text=record['Note'],
size_hint=(0.2, None), text_size=(self.width, None))
self.ids.layout.add_widget(existing_lbl)
def on_leave(self, *args):
self.ids.layout.clear_widgets()
def add_note(self):
sm.switch_to(screens[6], direction='left')
def go_back(self):
sm.switch_to(screens[0], direction='right')
.kv file:
< Reminders >:
name: 'Reminders'
FloatLayout:
Label:
text: "Notes"
color: (0, 0.702, 0, 1)
font_size: 50
pos_hint: {'x': 0.1, 'top': 1}
size_hint: 0.2, 0.2
Button:
size_hint: 0.07, 0.07
background_normal: 'plus.png'
pos_hint: {'x': 0.78,'top': 0.94}
on_release: root.add_note()
ScrollView:
size_hint: 0.96, 0.6
pos_hint: {'x': 0.02, 'top': 0.7}
StackLayout:
id: layout
orientation: 'tb-lr'
SmoothButton:
text: "Back"
pos_hint: {'x': 0.8, 'top': 0.15}
size_hint: 0.15, 0.05
on_release: root.go_back()
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.
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.
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.