Reputation: 1460
I've been pulling my hair out about this for hours. I have a custom widget that subclasses RelativeLayout
, which needs to be of a fixed size. I want this widget to display in the centre of the window. I will also want other, normal widgets (ie. buttons) to display around it. After spending an entire day getting the thing to centre in the first place, I now find that upon adding a button it resists all my attempts to get it to behave. Please could someone take a look at my .kv file and tell me where I'm going wrong?
#:kivy 1.8.0
# This is my fixed-size widget
<DrawableGrid>:
# Note: this is just an example size to keep things simple
size: 500, 500
canvas:
Color:
rgba: 1, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
# This subclasses BoxLayout
CustomLayout:
orientation: "vertical"
# I put my DrawableGrid inside an AnchorLayout in the hope that it might
# behave in some way like the documentation says it does. No such luck.
# This should be taking up the entire top half of the window.
AnchorLayout:
size_hint: 1, 1
# This anchor_x/anchor_y stuff seemingly does nothing.
anchor_x: "center"
anchor_y: "center"
# This should be appearing as a red rectangle of size 500x500
DrawableGrid:
# This next line was needed to set a custom size in the first place
size_hint: 0, 0
# This appears exactly as expected, filling the bottom half of the window.
Button:
id: next_button
text: "Next"
So, to reiterate, what I currently want is:
And what I actually get is this:
(as you can see, the red square is conspicuously absent)
I have tried a whole number of different ways (some more hacky than others) to get this work, but to no avail. Please can someone advise how I can fix this?
Upvotes: 1
Views: 4925
Reputation: 14814
RelativeLayout
positions all children relative to the layout's position. This includes all drawing instructions - because that's all children really are. All of a layout's children are drawn on the canvas
, so the positions used within the canvas
must be relative to the layout itself! So when you say in canvas
to draw the rectangle at self.pos
, that position is translated just like any other child (in other words, the rectangle is drawn at self.pos + self.pos
). If you change the rectangle pos to 0, 0
then it will draw as you expect.
To help explain, here is the default style for RelativeLayout
(from kivy/data/style.kv
):
<RelativeLayout>:
canvas.before:
PushMatrix
Translate:
xy: self.pos
canvas.after:
PopMatrix
Anything you put in canvas
happens between canvas.before
and canvas.after
.
Upvotes: 0
Reputation: 1072
I think you want a vertical BoxLayout as your root widget. The first widget in root will be a RelativeLayout and the second will be your button. This will give you the 50/50 split screen. The RelativeLayout will contain your 500x500 widget with a position of (self.parent.width-self.width)/2, (self.parent.height-self.height)/2
Note: in the following code example, I use 100x100 as the widget since 500x500 would not fit on my screen.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
kv = """
<Test>:
orientation: "vertical"
RelativeLayout:
GridLayout:
pos: (self.parent.width-self.width)/2, (self.parent.height-self.height)/2
size_hint: None, None
size: 100, 100
canvas:
Color:
rgba: 1, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
Button:
text: "Next"
"""
Builder.load_string(kv)
class Test(BoxLayout):
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
class TestApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()
Upvotes: 2