Kivy:如何使固定大小的控件居中显示在窗口中

1 投票
2 回答
4774 浏览
提问于 2025-04-18 07:00

我为这个问题纠结了好几个小时。我有一个自定义的控件,它是从RelativeLayout派生出来的,大小需要固定。我想让这个控件显示在窗口的中央。除此之外,我还想在它周围放一些普通的控件,比如按钮。花了一整天才把这个控件居中,现在我发现一添加按钮,它就不听话了,怎么都摆不对。请问有没有人能帮我看看我的.kv文件,告诉我哪里出错了?

#: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"

所以,简单说一下,我现在想要的是:

  • 窗口被分成上下两个部分(也就是上半部分和下半部分)
  • 上半部分应该包含我的自定义控件,大小为500x500,居中显示,周围什么都没有。这个控件应该显示为一个红色的正方形。
  • 下半部分应该包含一个文本为“下一步”的按钮,填满整个下半部分。

而我实际得到的是这个: 截图 (如你所见,红色正方形明显不见了)

我尝试了很多不同的方法(有些比较笨拙),但都没有成功。请问有没有人能告诉我该怎么解决这个问题?

2 个回答

0

RelativeLayout 是一种布局方式,它会根据布局的位置来安排所有子元素的位置。其实,所有的子元素都是一些绘图指令,所以说它们的定位都是相对于这个布局的。所有的子元素都会在一个叫 canvas 的画布上绘制,因此在 canvas 中使用的位置必须是相对于布局本身的!比如,当你在 canvas 中指示要在 self.pos 位置绘制一个矩形时,这个位置会像其他子元素一样被转换(换句话说,矩形会在 self.pos + self.pos 的位置绘制)。如果你把矩形的位置改成 0, 0,那么它就会按照你预期的那样绘制。

为了更好地解释,这里是 RelativeLayout 的默认样式(来自 kivy/data/style.kv):

<RelativeLayout>:
    canvas.before:
        PushMatrix
        Translate:
            xy: self.pos
    canvas.after:
        PopMatrix

canvas 中你放的任何东西都是在 canvas.beforecanvas.after 之间发生的。

2

我觉得你想要一个垂直的BoxLayout作为你的根部件。根部件中的第一个部件是RelativeLayout,第二个是你的按钮。这样可以让屏幕分成50/50的两部分。RelativeLayout里面会放一个500x500的部件,位置设置为(self.parent.width-self.width)/2, (self.parent.height-self.height)/2,这样它就会在屏幕中间显示。

注意:在下面的代码示例中,我用的是100x100的部件,因为500x500的部件在我的屏幕上放不下。

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()

撰写回答