beginner issues with layouts, widgets, sizes, canvas...

1,936 views
Skip to first unread message

toejough

unread,
Jan 25, 2013, 3:39:19 AM1/25/13
to kivy-...@googlegroups.com
Hi - I'm having serious problems getting anything to work the way I think it should. In the following code, I'm trying to create a simple grocery list. I'm trying to add colored backgrounds to the layout and the widgets so I can see where their boundaries are, too. Here's my code, with comments about what it is I *think* I'm doing:

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import *

class GroceryListLayout(FloatLayout):
   
def __init__(self, **kwargs):
       
# call parent init
       
super(GroceryListLayout, self).__init__(**kwargs)
       
# draw a red box where the layout is
       
self.canvas.add(Color(1,0,0))
       
self.canvas.add(Rectangle(pos=(0,0),size=self.size))
   
def add_widget(self, widget):
       
# place added widgets and space them apart some
       
# saw 30 as a good size in some other example...
        widget
.height = 30
        widget
.y = 35*len(self.children)
        widget
.x = 0
       
# draw a red box where each added widget is.
       
#  expecting red because that's the last color I set in
       
#  the canvas (in the constructor)
       
self.canvas.add(Rectangle(pos=(widget.x, widget.y), size=(widget.width, widget.height)))
       
# actually add the widget via the parent's add_widget method
       
super(GroceryListLayout,self).add_widget(widget)

class MyApp(App):
   
'''Boilerplate Kivy App Code'''
   
def build(self):
       
'''Build and return the main widget'''
       
# create the main widget with size 300x300
       
#  saw this size in the Float Layout docs as an example
        main_widget
= GroceryListLayout(size=(300,300))
       
# Add labels with grocery items to the widget
        main_widget
.add_widget(Label(text="milk"))
        main_widget
.add_widget(Label(text="eggs"))
        main_widget
.add_widget(Label(text="spam"))
        main_widget
.add_widget(Label(text="spam"))
        main_widget
.add_widget(Label(text="spam"))
       
return main_widget

if __name__ == '__main__':
   
# [Kivy App Startup]
   
MyApp().run()

Here's what I get when I run this code:


Why do my labels show up such that the first one is centered in the window? (the label stays centered even through resizing)
Why aren't they IN the layout, like the boxes that are set to their location and size?
Why are those boxes white, instead of red? (I realize if they were red, they'd be indistinguishable from their background, but the point is that I never changed the canvas color after setting it to red).
How do I set the window size? (this was the first question I asked in the forum - nobody's answered it)

When I try to resize the window on a MacBook, the boxes totally disappear. Is that an outright bug, or am I supposed to be catching some sort of "resize" event and manually redrawing things?

Please, can anyone explain? The docs just aren't doing it for me and my experimentation over the last few weeks has generally left me frustrated. I apologize for the shotgun questioning - I've been experimenting and reading the docs and working around things and I suddenly realized that either I still have a ton of fundamental misconceptions about how to use Kivy, or it's really, really broken. I'm hoping it's the former.

Thanks for any help!

toejough

unread,
Jan 25, 2013, 3:43:46 AM1/25/13
to kivy-...@googlegroups.com
Attached is the screenshot I tried to provide inline the first time.
Screen Shot 2013-01-25 at 1.15.45 AM.png

Gabriel Pettier

unread,
Jan 25, 2013, 5:41:56 AM1/25/13
to kivy-...@googlegroups.com
Hi

see inline answers :)


Le 25/01/2013 09:39, toejough a écrit :
Hi - I'm having serious problems getting anything to work the way I think it should. In the following code, I'm trying to create a simple grocery list. I'm trying to add colored backgrounds to the layout and the widgets so I can see where their boundaries are, too. Here's my code, with comments about what it is I *think* I'm doing:

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import *

class GroceryListLayout(FloatLayout):
   
def __init__(self, **kwargs):
       
# call parent init
       
super(GroceryListLayout, self).__init__(**kwargs)
       
# draw a red box where the layout is
       
self.canvas.add(Color(1,0,0))
       
self.canvas.add(Rectangle(pos=(0,0),size=self.size))
   
def add_widget(self, widget):
       
# place added widgets and space them apart some
       
# saw 30 as a good size in some other example...
        widget
.height = 30
        widget
.y = 35*len(self.children)
        widget
.x = 0
As GroceryListLayout is a FloatLayout, you need to take care of size_hint, which is (1, 1) by default, meaning the widget is the size of the parent (and width/height initial values are ignored/replaced), you can either change that to a more convenient fraction of 1 for you, or put None in either or both value, to desactivate, so the height/width you provide is used.

But i would suggest use a BoxLayout instead, it seems to do what you want, no?
        # draw a red box where each added widget is.
       
#  expecting red because that's the last color I set in
       
#  the canvas (in the constructor)
       
self.canvas.add(Rectangle(pos=(widget.x, widget.y), size=(widget.width, widget.height)))
You can't expect the color to be still there, canvas commands produces canvas instructions that are added (not directly applied) to the canvas, those are then applied anytime there is a need te redraw the screen, so the context will have changed when this instruction will be executed, and the current color will be the default one.

        # actually add the widget via the parent's add_widget method
       
super(GroceryListLayout,self).add_widget(widget)

class MyApp(App):
   
'''Boilerplate Kivy App Code'''
   
def build(self):
       
'''Build and return the main widget'''
       
# create the main widget with size 300x300
       
#  saw this size in the Float Layout docs as an example
        main_widget
= GroceryListLayout(size=(300,300))
as main_widget is your root widget, it takes the whole screen, so the size used here will be discarded as soon as the app goes live (but in your case, it will be used when you do add_widget, since it's before the widget is returned and used as root widget, that's why your canvas operations gets those as you intended, but the size is different later, as can be seen from the label behaviour, which comes from size_hint).

So you can either set the config to force the window to a certain size, and unresizable; use a Widget() as root widget, and put your GroceryListLayout inside, so that its size is not dependent of the window size; or design your app to be flexible, by using the properties of size_hint and the already existing widgets that helps for that. The latter being better, imho.
        # Add labels with grocery items to the widget
        main_widget
.add_widget(Label(text="milk"))
        main_widget
.add_widget(Label(text="eggs"))
        main_widget
.add_widget(Label(text="spam"))
        main_widget
.add_widget(Label(text="spam"))
        main_widget
.add_widget(Label(text="spam"))
       
return main_widget

if __name__ == '__main__':
   
# [Kivy App Startup]
   
MyApp().run()

Here's what I get when I run this code:


Why do my labels show up such that the first one is centered in the window? (the label stays centered even through resizing)
As mentioned earlier, because they use size_hint, so they automatically get resized (the size of the widget is not the size of the text), when their parent widget's size change, which happens when you return it as the root widget (since it has to fill the window).

Why aren't they IN the layout, like the boxes that are set to their location and size?
Why are those boxes white, instead of red? (I realize if they were red, they'd be indistinguishable from their background, but the point is that I never changed the canvas color after setting it to red).
Because of redraw in a different context, the color is long forgotten (and actively reset, i believe, to avoid such surprises)

How do I set the window size? (this was the first question I asked in the forum - nobody's answered it)

It's been asked over and over and over, if you search in the forum, you'll quickly find the answer (hint, use kivy.config.set before importing the rest of kivy).

When I try to resize the window on a MacBook, the boxes totally disappear. Is that an outright bug, or am I supposed to be catching some sort of "resize" event and manually redrawing things?
The box shouldn't disappear, i think it's a bug (either in kivy or in your opengl implementation), they don't disappear here (ubuntu).


Please, can anyone explain? The docs just aren't doing it for me and my experimentation over the last few weeks has generally left me frustrated. I apologize for the shotgun questioning - I've been experimenting and reading the docs and working around things and I suddenly realized that either I still have a ton of fundamental misconceptions about how to use Kivy, or it's really, really broken. I'm hoping it's the former.

Ok, did you read the programming guide 2 (http://kivy.org/docs/guide2-index.html) ? it's an ongoing effort, but tries to explain the fundamentals shortly, but yes, as others (and we know that mean we have to work on the docs), you have some misconceptions about how kivy works, it's OK to ask questions, did you try to play with the examples (in kivy/examples) ? they usually show atomic enough behaviour that you should be able to understand how things works, if the doc is not enough. Sorry for the inconvenience, we are aware the doc needs to be more throughout.
Thanks for any help!

--
 
 
You are welcome, if you need more, ask more, we'll try to answer :).

toejough

unread,
Feb 2, 2013, 7:33:06 PM2/2/13
to kivy-...@googlegroups.com
Hi,

A belated thanks for the answers - for some reason I couldn't log into the groups site after Google updated the interface.

I did read the documentation, but still didn't fully understand the operation of the canvas or the relationship between size-hint and actual sizes. Whether blame lies with the documentation or just my brain depends on how many other people have similar struggles, I suppose. Regardless, again, thank you for your quick response and calm explanation.

Regarding my choice of base layouts - I am aiming for a richer experience than I think the box layout provides. I'd like the user to be able to drag and drop to rearrange the list. Is the float the right choice for that behavior, or did I miss functionality in some of the others?

Regarding my desire to set the window size - I'm developing this app as a personal project, initially meant to go on my phone, and I'd like to have an estimate of what it would look like on my phone without having to install the new version whenever I make an incremental change that could affect display. I had read the forums prior to posting my initial question about window size, and posted the results of my experimentation there:

Config.set('graphics', 'height', '960')
Config.set('graphics', 'width', '540')
and that made the app about the right proportion, but in terms of pixels it was more like 1600x900
 
 (I'm on a Macbook Pro Retina). The actual pixels aren't so much a problem for me, but the screen ratio isn't quite right - whatever scaling factor is applied makes the window taller than my screen.

I tried changing the density via "kivy.metrics", but the only thing that changed was the font size.

I can decrease the height and width values I feed to the config module appropriately, but it bothers me that I don't understand the size/scaling settings.
Is there any way to control the scaling of the window size?

Thanks!

Reply all
Reply to author
Forward
0 new messages