I am trying to align labels and button in my test UI this is my kv file
<test>:
Label:
text: "foo"
color: 0,1,0,1
#pos:120,20
pos_hint:{"right":0.1,"top":1}
Label:
text:"boo"
color: 0,0,1,1
#pos:80,20
pos_hint:{"right":0.1,"top":0.5}
Label:
text:"bar"
color: 1,0,0,1
#pos:20,120
pos_hint:{"right":0.1,"top":0.1}
Button:
text:"goo"
size_hint:0.1,0.1
I am able to succesfully create labels foo,boo and bar using pos but when I used pos_hint it returns blank output?
You are getting "blank" output because the text of the labels is off screen (and the labels themselves are transparent).
Since your layout <test> has no size_hint so it takes on the
default of (1,1) which makes it the size of the Window (which is
800 x 600).
Your labels also don't have a size_hint so they default to the size of their parent - the layout, so they end up having size [800, 600]. The text in the labels is centered by default, and their background is transparent. (maybe you should try this with buttons first so you have a visual representation of the sizes)
Thus, the text a label with pos = (0,0) will appear in the center of the screen
Then we have the pos_hint taking different arguments (the below description might not be accurate for things outside of a FloatLayout):
pos_hint:{"right":v1,"top":v2} sets the pos to (self.parent.right*v1 - self.width, self.parent.top*v2 - self.height) - you are setting the top and right of the widget you are placing. Thus your labels get such negative coordinates that their texts never appear on screen (because bottom left is 0,0)
then we have pos_hint:{"x":v1,"y":v2} (which you may find more useful for your case), and pos_hint:{"center_x":v1,"center_y":v2}. You should be able to figure out how they work bearing in mind that the size affects how things looks, since pos only sets the bottom left coordinate.. you can play around with this .kv file:
#:kivy 1.0.9
<test>:
#size: (500, 500)
#size_hint:(None, None)
canvas:
Color:
rgb: 1,0,0
Rectangle:
size: (5,5)
pos: (0,0)
Widget:
id:wig
pos: (250,250)
canvas:
Color:
rgb: 1,1,1
Rectangle:
size: (5,5)
pos: self.pos
Label:
id: boo
text:"boo"
color: 0,0,1,1
#size_hint:(1,1)
pos_hint:{"center_x":1,"center_y":1}
Label:
id: foo
text: "foo"
color: 0,1,0,1
#size_hint: (.6,.6)
pos_hint:{"x":1,"y":1}
Label:
id: bar
text:"bar"
color: 1,0,0,1
#size:(500,500)
#size_hint:(None, None)
pos_hint:{"right":1,"top":1}
#pos:100, 10
Button:
text:"goo"
size_hint:0.1,0.1
pos:(1,1)
#some debug info, i know the code is ugly
on_press: print self.parent.size,'\n', self.parent.right, self.parent.top, self.parent.x, self.parent.y, self.parent.center_x, self.parent.center_y, "\n","bar_right_top:", bar.pos,"foo_x_y:", foo.pos,"boo_center:", boo.pos, "\nwhite square:", wig.pos, "\n", bar.size, foo.size, boo.size
Related
I need a rounded scrollview that rounds along with the children, I did a lot of research on this but failed, I didn't find anything about it.
Something like:
ScrollView:
do_scroll: [False, True]
radius: [dp(30),]
MDList:
id: list
This does not round the scrollview. Any idea how I can do thiswithout adding the RoundedRectangle chart?
Edit:
Adding the RoundedRectangle graph looks good, but it doesn't solve my problem. It is as if the children of the ScrollView exceeds the radius, the children do not fit in the radius.
ScrollView Code:
<RoundedScrollView#ScrollView>:
canvas.before:
Color:
rgba: 1, 0, 0, 1
RoundedRectangle:
pos: self.pos
size: self.size
radius: [0, 0, dp(80), 0]
Where I used ScrollView:
Screen:
RoundedSrollView:
MDList:
id: list
radius: [0, 0, dp(80), 0] #does not work
Result:
You can do something like this in your kv:
<RoundedScrollView#ScrollView>:
radius: 0
canvas.before:
Color:
rgba: 1, 0, 0, 1
RoundedRectangle:
pos: self.pos
size: self.size
radius: [self.radius]
This draws a red rounded rectangle as the background of a RoundedScrollView. You can add more Properties to the RoundedScrollView to control, for example, the color.
Well... After a long time (literally) I found a solution to define a radius to a ScrollView that automatically cuts the child. The solution is to redraw the ScrollView clipping using the canvas instructions StencilPush , StencilUse , StencilUnUse and StencilPop.
main.py
from kivymd.app import MDApp
from kivy.lang import Builder
KV = """
MDScreen:
MDScrollView:
do_scroll: [False, True]
size_hint: .5, .5
pos_hint: {"center":[.5, .5]}
canvas.before:
StencilPush
RoundedRectangle:
pos: self.pos
size: self.size
radius: [dp(50),]
StencilUse
canvas.after:
StencilUnUse
StencilPop
MDBoxLayout:
adaptive_height: True
size_hint_y: None
MDLabel:
text:
'The ScrollView accepts only one child and applies a viewport' \
'/window to it according to the scroll_x and scroll_y properties.' \
' Touches are analyzed to determine if the user wants to scroll or' \
' control the child in some other manner: you cannot do both at the' \
' same time. To determine if interaction is a scrolling gesture,' \
' these properties are used:'
adaptive_height: True
"""
class MyApp(MDApp):
def build(self):
return Builder.load_string(KV)
MyApp().run()
StencilPush is being used to save the current state of the Stencil and below it a rounded rectangle with the same dimensions and size as the ScrollView is being drawn.
StencilUse defines that this rounded rectangle will be the current Stencil.
After all the modifications have been made it is necessary to clean the "old" Stencil and set the modified Stencil as the default that was made under StencilPush. This is done using the StencilUnUse instruction and then the finalization, StencilPop, it is not mandatory but this ensures that all states are cleared and that performance is not affected.
So I am working on a file explorer user interface and I ran into a problem with the user interface. The user interface is basically divided into two parts. One of the parts contains a MDBackdrop. I wanted to position this Backdrop at the right side of the screen. So I added it into a BoxLayout and positioned it to the side of the screen as shown...
<MainScreen>:
FloatLayout:
canvas:
Color:
rgba: 0.05,0.05,0.05, 1
Rectangle:
pos: root.pos
size: root.size
Color:
rgba: 0.1, 0.1, 0.1, 1
RoundedRectangle:
size:(root.width-10, root.height-10)
pos:(5,5)
radius: (30,30,30,30)
Color:
rgba: 0.15, 0.15, 0.15, 1
RoundedRectangle:
pos:(10,10)
size:(400,root.height-20)
radius: (30,30,30,30)
BoxLayout:
size:500,500
size_hint_y : None
size_hint_x : None
pos_hint:{"right":1, "top": .95}
MDBackdrop:
I also had to modify the source code of the Backdrop so that the actual back element and the toolbar at the top of the widget will be positioned correctly. The source code is at https://raw.githubusercontent.com/HeaTTheatR/KivyMD/master/kivymd/uix/backdrop.py
The line I changed is I added
pos:root.pos
after line 176 i.e. told the _frontLayer to follow the positioning of the root class(Backdrop)
I also want the toolbar to appear at the right of the screen rather than the left side of the screen so
I changed(line 162 i.e.MDBackdropToolbar)
pos_hint: {'top': 1,}
to
pos_hint: {'top': 1, 'right':1}
the toolbar shift correctly but I get this extra blue rectangle which I just cannot figure out why and how to remove it...
That weird rectangle that I see
I have no idea why that rectangle keeps on showing up and how do I remove it? THANKS :)
So I found out the answer myself ;). Turns out nothing was wrong with MDBackdrop Widget it was actually the toolbar widget that was causing that weird rectangle. I edited the source code of the toolbar widget which can be found here https://raw.githubusercontent.com/HeaTTheatR/KivyMD/master/demos/kitchen_sink/studies/shrine/baseclass/toolbar.py
and I changed line 281 from
(root.action_button.width - dp(6), self.height)) if root.type == "bottom" else self.pos
to
(root.action_button.width - dp(6), self.height)) if root.type == "bottom" else self.size
i.e. I changed self.pos to self.size
and now that weird rectangle is gone
The way I intended it to look like without that weird rectangle
I'm looking for how I can change the font size of all text in a kivy FileChooserListView class. I am hoping to do so in pure python if possible. I like that the standard Label and Button uix classes take font_size as an initialize parameter, but it appears the FileChooserListView does not. If doing so in pure python isn't an easy approach and there's a good .kv file approach, I'd take that too. Thanks!
There is no direct way to do that, but you can fiddle with the FileListEntry template that the FileChooserListView uses to display the entries. In that template, you can adjust the font sizes used. Here is my attempt at that:
Builder.load_string('''
[FileListEntry#FloatLayout+TreeViewNode]:
locked: False
entries: []
path: ctx.path
# FIXME: is_selected is actually a read_only treeview property. In this
# case, however, we're doing this because treeview only has single-selection
# hardcoded in it. The fix to this would be to update treeview to allow
# multiple selection.
is_selected: self.path in ctx.controller().selection
orientation: 'horizontal'
size_hint_y: None
height: '96dp' if dp(1) > 1 else '48dp' # height must be big enough to hold font sized below
# Don't allow expansion of the ../ node
is_leaf: not ctx.isdir or ctx.name.endswith('..' + ctx.sep) or self.locked
on_touch_down: self.collide_point(*args[1].pos) and ctx.controller().entry_touched(self, args[1])
on_touch_up: self.collide_point(*args[1].pos) and ctx.controller().entry_released(self, args[1])
BoxLayout:
pos: root.pos
size_hint_x: None
width: root.width - dp(10)
Label:
id: filename
font_size: '48dp' # adjust this font size
size_hint_x: None
width: root.width - sz.width # this allows filename Label to fill width less size Label
text_size: self.width, None
halign: 'left'
shorten: True
text: ctx.name
Label:
id: sz
font_size: '48dp' # adjust this font size
#text_size: self.width, None
size_hint_x: None
width: self.texture_size[0] # this makes the size Label to minimum width
text: '{}'.format(ctx.get_nice_size())
''')
This is based heavily on the FileListEntry template in style.kv. There are two font_sizes that you can adjust, and a height for the entry. All three must be coordinated to get a reasonable result.
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.
Hi I recently tried my hands on kivy graphics, context instructions(rotate, ranslate etc). So i tried to implement an animated spinning wheel(used for example to show loading screen). I used garden.iconfonts package for this purpose following closely the example implemented in the package. Heres my code
.kv
<Convert>:
pos_hint: {'center_x':.5, 'center_y':.5}
size_hint: .8,.4
auto_dismiss: False
on_open:
self.load()
loading:loading
BoxLayout:
pos: root.pos
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
source: 'icons/olivine.png'
orientation: 'vertical'
Label: #STATUS 20 PERCENT
text: 'Converting file...'
id: status
size_hint: 1,.2
markup: True
RelativeLayout: #picture or rolling 60 %
size_hint: 1,.6
Label: #SPINNER
text: '{}'.format(icon('icon-spin6', 32))
size_hint: 1,1
markup: True
p: 0
id: loading
canvas:
PushMatrix
Rotate:
angle: -self.p
origin: self.center
axis: 0,0,1
PopMatrix
.py
from kivy.uix.modalview import ModalView
from kivy.properties import ObjectProperty
from kivy.animation import Animation
class Convert(ModalView):
loading= ObjectProperty()
def load(self):
anim = Animation(p = 360, duration= 1) + Animation(p=0 , duration=0)
anim.repeat = True
anim.start(self.loading)
From my code Convert is a popup that shows up when a button is clicked, then as it opens, shows the spinning wheel.
But when i run the code it just shows the wheel(i.e the iconfont), but does not spin.
The code only works when i change the canvas class under the Label, to canvas.before. I assume that my understanding of how to use these tools is still poor. So im hoping someone can help clearify what im doing wrong, and how to make this work using canvas
canvas:
PushMatrix
Rotate:
angle: -self.p
origin: self.center
axis: 0,0,1
PopMatrix
Everything between Rotate and PopMatrix will be rotated - that's the point of PushMatrix and PopMatrix, they bound the region where any matrix transformations are applied.
In this case, you didn't put anything in beween them, so you don't see anything rotated.
You probably want to put PushMatrix and Rotate in the canvas.before, and PopMatrix in the canvas.after. Since the Label drawing occurs in canvas, this will then be in the rotated state.