I'm brand new to Kivy, and am working on the UI to get a fairly complex set of widgets to display properly. My root widget is a boxlayout(horiz), and I'm trying to get 2 floatlayouts to appear side by side. But the second floatlayout displays on the left side of the boxlayout over the first floatlayout. I've tried with and without pos_hints and size_hints at the floatlayout level, to no avail. Some base code:
<BoxLayout>:
id: rootwid
orientation: 'horizontal'
FloatLayout:
id: leftside
pos_hint: {'x':0, 'y':0} (Also tried 'right' and 'top' and commenting out the line)
#size_hint: (.5, 1)
(Buttons & Labels here, which lay out properly within the floatlayout)
FloatLayout:
id: rightside
pos_hint: {'x': .5, 'y':0} (Also tried 'right' and 'top' and commenting out the line)
#size_hint: (.5, 1)
(Buttons & Labels here, which lay out properly within the floatlayout)
What am I missing? Thanks!
unless you have a future use for the FloatLayouts, I advise that you replace them with other types of layouts bcoz since they are float, they tend to be independent of the parent.
Try using GridLayout to house the buttons and labels and other widgets
like this;
BoxLayout:
orientation: 'horizontal'
GridLayout:
cols: any
rows: any
# Left widgets added here
GridLayout:
cols: any
rows: any
# Right widgets added here
You can also nest them accordingly, for extensize insight on these run KivyCatalog , an inbuilt python file in kivy-examples,
usually at ~/.local/share/kivy-examples/demo/kivycatalog/main.py for Ubuntu
for windows i think check AppData then local then share, AppData is by default hidden , dont forget that.
KivyCatalog is interative as it shows you changes in your kv code as you write it,try it.
Related
So I'm able to use the video library to play video on my GUI, but I realized the video was always placed at the middle with the default size, as there are no attribute like pos or size in video class. I would like to know if there are any way I can size and place the video like other widgets/buttons/labels.
The following example illustrates sizing and placing a video.
Example
In the following demo, we are using AnchorLayout. You can replace it with any Layouts (BoxLyout, FloatLayout, etc.), Widget, etc. and use pos or pos_hint.
main.py
from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string("""
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
Video:
source: 'rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov'
state: 'play'
keep_ratio: True
allow_stretch: True
size_hint: 0.8, 0.8
"""))
I'm new to Kivy and I trying to get myself an kind of template for later upcoming program parts.
Now I'm stuck because my wonderful round .png Buttons all get King of "edges/bumps" when I try to resize them.
This is how the Button should look like ...
... and this is what actually happens (please ignore the white background)
I tried it with multiple other .png's so I'm very sure that the problem is not within the .png itself.
Here is my code (I shortened it so that its easy to find the relevant part. if you feel like you need more code, of course I can add it):
test.kv
#:kivy 1.0.9
<MainWindow>:
BoxLayout:
#[shortened for readability reasons]
BoxLayout:
#[shortened for readability reasons]
BoxLayout:
#[shortened for readability reasons]
AnchorLayout:
#[shortened for readability reasons]
FloatLayout:
canvas:
Rectangle:
pos: self.pos
size: self.size
Button:
id: leftButton
background_normal: 'assets/graphics/buttons/dummy.png'
background_down: 'assets/graphics/buttons/.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
Perhaps someone here has an idea whats the problem and how to fix it?
Please keep in mind that I want to fix that in the .kv file (if possible) so I can reuse it later on more easily.
Another minor problem is the positioning of some other buttons. I want to get them aligned to the right side, but I couldn't find how to access the width of the button itself so I can subtract it from self.width (which should be the width of the surrounding layout if I got that right)
Any suggestions?
I did a little testing in the meantime to be sure that the file type isn't the problem here. I tried with .gif and .tif, as far as I know the other most common file types that support transparency.
The outcome is the same as with .png
To clarify how the design should look in the end I'll add another picture:
So I think I have to do it with a FloatLayout. I would like to do it with grid like in pyqt, but in kivy it's not possible to define the cell in which the widget should be placed and also not to give it a colspan or rowspan. At least that's what I've read. Please correct me if I'm wrong.
Ok, ikolim's solution works so far, but creates another problem: I can't use background_normal and background_down anymore, but I feel like I must give the user a visual feedback on - for example -clicking the button and holding it down. I thought because I use ButtonBehavier I can also use the background-stuff. But that does not seem to be the case. Anyone out there who can give me a hint on how to solve that?
UPDATE: I got the visual feedback to work now. The solution was that simple that I overlooked it until last friday (and I coul'd come back to a computer with internet until now).
So for the interrested reader with similar problems, here is my solution:
I now just use the on_press and on_release listeners and change the source of the image there from myPic.png to myPic_clicked.png and vice versa.
So the problem is solved and I will write a complete answer and close this question in a few days.
BUT until then, I would really like to know if someone has an idea, WHY I got this bumps. For overall understanding in kivy on the one hand, and on the other hand for avoiding that Problem in future.
Thx in Advance!
Create a custom button with inheritance of ButtonBehavior and Image
Use a GridLayout to place the custom buttons in a row
Example
main.py
from kivy.lang import Builder
from kivy.base import runTouchApp
runTouchApp(Builder.load_string('''
#:kivy 1.11.0
<CustomButton#ButtonBehavior+Image>:
GridLayout:
rows: 1
canvas:
Rectangle:
pos: self.pos
size: self.size
CustomButton:
id: Button0
source: './dummy.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
on_release:
print('CustomButton clicked')
CustomButton:
id: Button1
source: './dummy.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
on_release:
print('CustomButton clicked')
CustomButton:
id: Button2
source: './dummy.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
on_release:
print('CustomButton clicked')
CustomButton:
id: Button3
source: './dummy.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
on_release:
print('CustomButton clicked')
'''))
Output
Ok, after no one else seems to know what the Original Problem was, here at least a solution that works quite nice.
ikolims answer is nearly perfectly correct, and I want to honor that. But it also misses an - at least for me - important part. Here is his code. After that I will explain whats missing:
from kivy.lang import Builder
from kivy.base import runTouchApp
runTouchApp(Builder.load_string('''
#:kivy 1.11.0
<CustomButton#ButtonBehavior+Image>:
GridLayout:
rows: 1
canvas:
Rectangle:
pos: self.pos
size: self.size
CustomButton:
id: Button0
source: './dummy.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
on_release:
print('CustomButton clicked')
CustomButton:
id: Button1
source: './dummy.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
on_release:
print('CustomButton clicked')
CustomButton:
id: Button2
source: './dummy.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
on_release:
print('CustomButton clicked')
CustomButton:
id: Button3
source: './dummy.png'
size_hint: .15, .15
pos_hint: {'x':root.size_hint_x/2, 'y':root.size_hint_y/2}
on_release:
print('CustomButton clicked')
'''))
The thing is, that if we do that this way the bug with that bumps is gone. But also gone is background_normal and background_down do not work anymore. The solution to this is to use on_pressed and on_release instead and change the source in there.
I am in a bit of a predicament. While working with Kivy's ScrollView Layout and (Current Experimental) reStructuredText renderer module, I ran into a slight problem. Whenever I run my code, my terminal spams me with:
[CRITICAL] [Clock] Warning, too much iteration done before the next frame. Check your code, or increase the Clock.max_iteration attribute
Now, the application seems to run perfectly fine, until you get to the page with the rST Document inside a ScrollView Layout. That page does all kinds of odd things. The Main scroll view will slowly scroll down, forever, trailing off the page into whiteness, and the rST document is placed oddly, shifted slightly to the left.
When I remove the document though, the screen and application behave perfectly normal, running smoothly. Does anyone have any idea as to how I could fix this, to make the page work correctly? (Did I mention the rST Document was originally in a Carousel, but I took out the carousel to see if that was the problem.)
Here is the Kivy Language Code:
<Page>:
orientation: 'vertical'
ScrollView:
size_hint: (.99, .99)
StackLayout:
size_hint_y: None
id: content_layout
height: self.minimum_height
WrappedLabel:
text: "Test"
font_size: min(root.height, root.width)
RstDocument:
underline_color: 'blue'
text:("Some Text")
Could the problem be that rST Documents are based off of the ScrollView Layout by any chance?
Sometimes height: self.minimum_height and similar stuff are like shooting yourself in a foot. Definitely try to comment out these things first, because if you don't do something fancy, the sizing is the issue.
Now, why is it an issue? StackLayout has its minimum_height set from minimum_size, which is set I think somewhere here and has some initial value that is not zero.
Don't be confused though, minimum_height really defaults to zero at the beginning, but then it's recalculated probably on each added widget or so. If you add on_height: print(self.height) after your height: self.minimum_height, you'll see what I mean.
Why does it do it like that? Simple! You didn't set absolute size for those children (each child has size_hint == [1, 1]).
Also, ScrollView expects size bigger that the ScrollView if I remember correctly (so that it would scroll).
from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
Builder.load_string('''
<Test>:
orientation: 'vertical'
ScrollView:
size_hint: (.99, .99)
StackLayout:
size_hint_y: None
id: content_layout
height: self.minimum_height
on_height: print(self.height)
Label:
size_hint: None, None
size: 100, 30
text: "Test"
font_size: min(root.height, root.width)
RstDocument:
size_hint: None, None
size: 100, 1000
underline_color: 'blue'
text:("Some Text")
''')
class Test(BoxLayout): pass
runTouchApp(Test())
Remove size_hint and size from children and you have your too much iteration there.
I am trying to do some simple math in a kivy app using TextInput to allow users to input values. I defined the TextInput in the kv section of the code. I am unsure how to create a simple submit button to assign what's in the TextInput (which is defined in kv) to a variable so that I can do basic math with it in the python section.
You'll want to do something like the following:
BoxLayout:
orientation: 'vertical'
TextInput:
id: ti
Button:
text: 'do something!'
on_press: run_some_function_with_text(ti.text)
run_some_function_with_text would probably most usefully be a method of some other widget, but could be anything else you like, or you could just write the function inline if it's simple.
I would like to create an app in kivy with widgets in a grid and I want to be able to set some widgets to be larger - to occupy more than one cell in a grid.
GridLayout seems the most appropriate, but it seems to not support placing widgets in more than one cell.
To be more specific I want behavour similar to the grid geometry manager from Tkinter, when setting columnspan or rowspan to more than 1.
Like this:
(widget)(widget)(widget)
( bigger widget )(widget)
...
I would prefer to be able to do this using existing kivy layouts instead of having to write my own layout class to handle this, but if no other option is possible, this is also ok.
Another option here is to have a GridLayout with 1 column and populate each row with a BoxLayout with orientation="horizontal". You can then format each BoxLayout (row) as you want.
For more info on the BoxLayout: http://kivy.org/docs/api-kivy.uix.boxlayout.html
I don't think a GridLayout is really suitable, it just isn't designed for quite that usage.
If I personally had to do this, I'd probably make my own Layout class, it wouldn't need a very complicated do_layout method.
One possible start point would be the SparseGridLayout I made a while ago. You could very easily add column and row span properties to it...actually, I'll probably add them myself now that you've given me the idea!
That might not be ideal if you have a big grid full of widgets, in which case something similar to a gridlayout might be better, or possibly a combination of multiple layouts if the spanning widgets are in a particular pattern.
Lets assume you have a GridLayout with two columns and you want to span the first row.You can add Two FloatLayout whereby the first FloatLayout will contain the widget you would like to span while the second Layout will have row and height values to zero.This would archive a span effect
here is an example of .kv span effect
GridLayout:
cols:2
FloatLayout: # The first FloatLayout in the first column in the gridLayout
size_hint:None,None
size: 0,50
BoxLayout:
size_hint: None,None
size: root.width-40,50
pos_hint: {'x':.5,'center_y':.5}
BoxLayout:
padding:0,0,5,0
Label:
id:lbl_unknown
text:'Accession number :'
TextInput:
text:''
FloatLayout: # The second FloatLayout in the second column of the gridLayout
size_hint:None,None
size:0,0
Label:
text:'Label 1:'
TextInput:
Label:
text:'Label 2:'
TextInput:
An easy work around is to pack BoxLayout objects into any type of parent layout you want using your better judgement to decide the orientation of each subsequent BoxLayout
(decided to use box layouts for almost all of my own project over any gridlayout)
This is my class:
class AuthPage(BoxLayout):
def __init__(self, **kwargs):
super(AuthPage, self).__init__(**kwargs)
self.orientation = 'vertical'
self.add_widget(Label(text='Authenticate'))
unameRow = BoxLayout(orientation='horizontal')
unameRow.add_widget(Label(text='User Name'))
unameRow.username = TextInput(multiline=False)
unameRow.add_widget(unameRow.username)
self.add_widget(unameRow)
pwordRow = BoxLayout(orientation='horizontal')
pwordRow.add_widget(Label(text='password'))
pwordRow.password = TextInput(password=True, multiline=False)
pwordRow.add_widget(pwordRow.password)
self.add_widget(pwordRow)
self.add_widget(Button(text='authenticate'))