I'm creating an app with Kivy and I want it to have a header with an Image at the left corner and some buttons like a menu on this Image's right side. The problem is that I can't reposition the Image. I'm able to resize it but its position is always on the starting position of the BoxLayout.
I've tried changing its position with pos_hint and pos. Also tried resizing the Image with size_hint or setting size_hint to (None, None) and them tried to change its position again and none of them works. I've also added some buttons on the ScrollView below it that when pressed show the Image's position to check if something works.
Here is the Kvfile, I'm just pasting the Screen(SomeScreen) widget where this problem is ocurring
<SomeScreen>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
id: box
size_hint: 1, 0.12
canvas:
Rectangle:
size: self.size
pos: self.pos
Image:
id: img
size_hint: None, 0.9
width: 200
pos: 200, 600
allow_stretch: True
source: 'image.png'
ScrollView:
id: scr
BoxLayout:
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(f'image size: {img.size}, image postion {img.pos}')
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(box.size, box.pos)
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(scr.size, scr.pos)
I'd like to change the image's position to whatever I choose
A couple things to note:
You are using a BoxLayout with orientation set to vertical.
That will position your widgets vertically, so the ScrollView
will not be to the right of your Image.
You have a second BoxLayout inside your first BoxLayout that
appears to serve no purpose. However, putting your Image in a
horizontal(the default) BoxLayout, means that you cannot adjust
the horizontal position of the Image
Not sure if I have captured what you intention is, but here is a modified version of your kv that, I think, is more along the lines of what you asked for:
<SomeScreen>:
BoxLayout:
Image:
id: img
size_hint: None, 0.12
width: 200
pos_hint: {'center_y':0.5}
allow_stretch: True
source: 'image.png'
ScrollView:
id: scr
BoxLayout:
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(f'image size: {img.size}, image postion {img.pos}')
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(box.size, box.pos)
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(scr.size, scr.pos)
Related
<Builder_Screen>
ScrollView:
do_scroll_y:True
FloatLayout:
Button:
text:"Heading"
size_hint_x: .25
size_hint_y: .25
text_size: self.size
halign:"center"
valign:"center"
pos: 0,10
Button:
text:"Paragraph"
halign:"center"
valign:"center"
size_hint_x: .25
size_hint_y: .25
pos: (0,self.height)
I have some buttons like these with positions like pos: 0, self.height2 , self.height3 etc.
But, the scroll layout does not work as intended.
Can you help me regarding that!...
According to the documentation, regarding the child of a ScrollView:
By default, the size_hint is (1, 1), so the content size will fit your
ScrollView exactly (you will have nothing to scroll). You must
deactivate at least one of the size_hint instructions (x or y) of the
child to enable scrolling.
So, you probably need to set size_hint_y: None for your FloatLayout. That will cause further problems, because you have size_hint_y values for your Buttons. You can set the heights of your Buttons and eliminate the size_hint_y values. Another approach would be to use a GridLayout:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
kv = '''
<Builder_Screen>
ScrollView:
do_scroll_y:True
effect_cls: 'ScrollEffect'
GridLayout:
cols: 2
size_hint_y: None
height: self.minimum_height
padding: 5
spacing: 5
Button:
text:"Heading1"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Paragraph1"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Heading2"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Paragraph2"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Heading3"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Paragraph3"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
'''
class Builder_Screen(Screen):
pass
class TestApp(App):
def build(self):
Builder.load_string(kv)
return Builder_Screen()
TestApp().run()
Note that every Button has an explicit height. That is required if you use height: self.minimum_height for their container.
Ok, so I'm building something with Kivy(1.11.1) and summarizing I have a ScrollView that scrolls vertically and inside it there are some others ScrollViews but these ones only scroll horizontally, the problem is that whenever I scroll the outer ScrollView down and the mouse position gets into the inner Horizontal ScrollViews the outer Scrollview stops scrolling down, it looks like once the mouse position collides with the horizontal scrollview the scroll behavior stops being sent to the outer ScrollView (vertical) so it stops scrolling down. What I want is something like the Netflix page, in which there are some scrollviews horizontally (My List, Series, Horror Movies, etc) that you can scroll to see more options but they're all inside an outer scrollview that scrolls vertically, of course that in Netflix when you scrolldown even if your mouse position get inside one of the horizontal scrollviews it still continue scrolling the outer ScrollView down.
I've tried setting the horizontall scrollview do_scroll_y to False but the problem goes on. Besides that. Scrolling up works just fine
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
Builder.load_string(
'''
<ScrollApp>:
ScrollView:
bar_width: 10
scroll_type: ['bars', 'content']
BoxLayout:
id: content
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
padding: 22, 0, 22, 50
spacing: 50
canvas:
Color:
rgba: .15, .15, .15, .9
Rectangle:
size: self.size
pos: self.pos
Button:
size_hint: None, None
width: 100
height: 100
on_press: print('pressed')
# "ScrollViews containers"
Custom
Custom
Custom
Custom
<Custom#BoxLayout>:
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
Label:
size_hint: None, None
size: self.texture_size
id: label
font_size: 20
ScrollView:
size_hint: 1, None
height: 150
do_scroll: True, False
on_scroll_start: print('scrolling. but why?')
GridLayout:
id: grid
size_hint: None, None
size: self.minimum_width, 150
spacing: 5
cols: 3
Button:
size_hint: None, None
size: 400, 150
Button:
size_hint: None, None
size: 400, 150
Button:
size_hint: None, None
size: 400, 150
''' )
class ScrollApp(BoxLayout):
pass
class Test(App):
def build(self):
return ScrollApp()
Test().run()
I can't claim to understand this situation completely, but it seems that vertical ScrollView inside another vertical ScrollView works. So, a work around is to make the ScrollView inside your Custom class to allow vertical scrolling (along with the horizontal scrolling). To do this, change the kv for the ScrollView inside Custom to:
ScrollView:
size_hint: 1, None
height: 150
do_scroll: True, True # allow vertical scrolling also
on_scroll_start: print('scrolling. but why?')
GridLayout:
id: grid
size_hint: None, 1.01 # height must be slightly greater than ScrollView height
width: self.minimum_width
In order for the vertical scrolling to work in the above, the height of the GridLayout must be larger than the height of the ScrollView, thus the 1.01 size hint.
I would like to ask your help.
The scrollable structure under the link is what I want to generate.
As the Scrollview accept only one element, I used a GridLayout. Somehow I cannot put any Boxlayout in the GridLayout.
Could you help me? Did I made a mistake? Should I use maybe an other Layout? if yes, which one?
Thank you.
Here is the output of my .kv file: http://imgur.com/etilRPg
Here is the result, if I change cols:1 to cols:2 : http://imgur.com/ihWla4Y
Here is the code I tried in the .kv file:
#:kivy 1.8.0
RootWidget:
# import container
container: container
# fill container
BoxLayout:
id: container
orientation: 'vertical'
padding: 0
spacing: 3
ScrollView:
size_hint: 1, 1
pos_hint: {'center_x': .5, 'center_y': .5}
GridLayout:
cols: 1
padding: 0
spacing: 3
size_hint: 1, None
height: self.minimum_height
do_scroll_x: False
BoxLayout:
height: 260
orientation: 'horizontal'
canvas.before:
Color:
rgb: 0.7, 0.7, 0.9
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
height: 260
orientation: 'horizontal'
canvas.before:
Color:
rgb: 0.7, 0.7, 0.9
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
height: 260
orientation: 'horizontal'
canvas.before:
Color:
rgb: 0.7, 0.7, 0.9
Rectangle:
size: self.size
pos: self.pos
#type
Label:
height: 260
size_hint: 1, None
text: 'Typ'
BoxLayout:
height: 260
orientation: 'horizontal'
canvas.before:
Color:
rgb: 0.7, 0.7, 0.9
Rectangle:
size: self.size
pos: self.pos
If you want to set height or width or anything else with sizing you need to do something first in a widget you want to set it for:
size_hint: None, None
This will disable setting those properties according to parent's size and some other stuff i.e. number of widgets in parent (three widgets = parent's size / 3 for each) at least for layouts such as BoxLayout or GridLayout. Check docs for more.
Alternatively use size_hint_x: None or size_hint_y: None and let the other part be set automatically if you only want to set one of height or width.
I'm new to Kivy and still working out the best way to use it. Currently, I'm taking an example from their repo (textsize demo) and attempting to use layout concepts in a personal project.
At the end of the day, all I want is a "navbar" at the top of my screen and a content section below it. At the moment, I'm trying to accomplish this with a BoxLayout which includes a StackLayout (nav items) and a GridLayout (other content).
My Code Snippet:
<WindowWidget>:
BoxLayout:
orientation: 'vertical'
StackLayout:
Label:
text: 'Test1'
Label:
text: 'Test1.1'
Label:
text: 'Test2'
This code produces this: Kivy Screenshot.
I don't understand why label 1.1 is pushed down on top of label 2 rather than appearing beside label 1.
I added the following code taken from the kivy examples hoping the height setting would add some clarity, but I get the error below:
Code:
<StackLayout>:
size_hint_y: None
spacing: dp(6)
padding: dp(6), dp(4)
height: self.minimum_height
Error:
Warning, too much iteration done before the next frame. Check your
code, or increase the Clock.max_iteration attribute
This is caused by my inclusion of the "height: self.minimum_height" line. However, this works in the demo, so I'm not sure how I managed to screw it up. I'll include the example's kv code below for reference.
The original:
BoxLayout:
orientation: 'vertical'
HeadingLabel:
text: 'These modify all demonstration Labels'
StackLayout:
# Button is a subclass of Label and can be sized to text in the same way
Button:
text: 'Reset'
on_press: app.reset_words()
ToggleButton:
text: 'Shorten'
on_state:
app.shorten=self.state=='down'
ToggleButton:
text: 'max_lines=3'
on_state:
app.max_lines=3 if self.state=='down' else 0
Spinner:
text: 'bottom'
values: 'bottom', 'middle', 'top'
on_text: app.valign=self.text
Spinner:
text: 'left'
values: 'left', 'center', 'right', 'justify'
on_text: app.halign=self.text
GridLayout:
id: grid_layout
cols: 2
height: cm(6)
size_hint_y: None
HeadingLabel:
text: "Default, no text_size set"
HeadingLabel:
text: 'text_size bound to size'
DemoLabel:
id: left_content
disabled_color: 0, 0, 0, 0
DemoLabel:
id: right_content
text_size: self.size
padding: dp(6), dp(6)
ToggleButton:
text: 'Disable left'
on_state:
left_content.disabled=self.state=='down'
# Need one Widget without size_hint_y: None, so that BoxLayout fills
# available space.
HeadingLabel:
text: 'text_size width set, size bound to texture_size'
text_size: self.size
size_hint_y: 1
DemoLabel:
id: bottom_content
# This Label wraps and expands its height to fit the text because
# only text_size width is set and the Label size binds to texture_size.
text_size: self.width, None
size: self.texture_size
padding: mm(4), mm(4)
size_hint_y: None
# The column heading labels have their width set by the parent,
# but determine their height from the text.
<HeadingLabel#Label>:
bold: True
padding: dp(6), dp(4)
valign: 'bottom'
height: self.texture_size[1]
text_size: self.width, None
size_hint_y: None
<ToggleButton,Button>:
padding: dp(10), dp(8)
size_hint: None, None
size: self.texture_size
# This inherits Button and the modifications above, so reset size
<Spinner>:
size: sp(68), self.texture_size[1]
<DemoLabel#Label>:
halign: app.halign
valign: app.valign
shorten: app.shorten
max_lines: app.max_lines
canvas:
Color:
rgb: 68/255.0, 164/255.0, 201/255.0
Line:
rectangle: self.x, self.y, self.width, self.height
<StackLayout>:
size_hint_y: None
spacing: dp(6)
padding: dp(6), dp(4)
height: self.minimum_height
TYIA
I'm usng kivy and the kv languge to make a GUI, I'm still only new to kivy.
In the image below the the buttons were in the black bit on the right side of the GUI but the scrollview buttons on fitted half of the height of the screen to I put an extra floatlayout in the rule and indented everything but now all the buttons are on the wrong side of the screen.
#:kivy 1.9.0
GridLayout:
rows: 1
LeftArea:
RightArea:
<LeftArea#FloatLayout>:
canvas:
Color:
rgb: 0, 1, 0
Rectangle:
size: self.size
pos: self.pos
Image:
source: 'moneyswags.gif'
size: self.size
pos: self.pos
<RightArea#GridLayout>:
cols: 1
size_hint_x: 0.3
spacing: '10dp'
FloatLayout:
ScrollView:
LinksGrid:
id: links_grid
BoxLayout:
cols: 1
rows: 2
GetLinksButton:
links_grid: links_grid
Clearlinkbuttons:
links_grid: links_grid
<LinksGrid#GridLayout>:
cols: 1
spacing: '5dp'
size_hint_y: None
height: self.minimum_height
<GetLinksButton>:
size_hint_y: 0.1
text: 'get links'
on_press: self.get_links()
<Clearlinkbuttons>:
size_hint_y: 0.1
text: 'clear links'
on_press: self.clear_links()
<LinkButton>:
size_hint_y: None
height: '80dp'