当我将 Widget 对象添加到 .kv 文件中的 BoxLayout 时,它会按照我的预期操作并填充屏幕顶部的可用空间。但是,当我在 Python 中动态添加 Widget 时,它不会出现在屏幕顶部,也不会像我预期的那样占用屏幕的全部剩余空间。
我创建了一个小示例程序来演示我的问题。
当我将 Widget 对象添加到 .kv 文件中的 BoxLayout 时,它会按照我的预期操作并填充屏幕顶部的可用空间。这是 kv 文件和结果屏幕:
KV 文件
BoxLayout:
orientation: 'vertical'
Widget:
canvas:
Color:
rgb: 1, 0, 0
Rectangle:
size: self.size
pos: self.pos
Button:
size_hint: .5, None
pos_hint: {'center_x': .5}
height: 100
text: 'My Button'
结果:
当我从 kv 文件中取出 Widget 并尝试在单击按钮时将其动态添加到 BoxLayout 中时,它不会出现在屏幕顶部,也不会按预期占用全部剩余空间。
新的 KV 文件(test.kv):
BoxLayout:
orientation: 'vertical'
Button:
size_hint: .5, None
pos_hint: {'center_x': .5}
height: 100
text: 'My Button'
on_release: app.on_btn_release()
Python:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.graphics import Color, Rectangle
class TestApp(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
def on_btn_release(self):
wid = Widget()
wid.size_hint = (1,1)
with wid.canvas:
Color(rgb=(1,0,0))
Rectangle(size=wid.size, pos=wid.pos)
self.root.add_widget(wid, 1)
if __name__ == '__main__':
TestApp().run()
结果:
我尝试将画布指令移至 add_widget() 调用之后,但这没有帮助。我知道问题在于,在将指令添加到画布时,尚未调整小部件的大小以填充框布局。我知道这一点,因为如果我添加第二个按钮来添加画布指令,并在单击第一个按钮后单击该按钮,则它可以正常工作。我只是想知道如何在单击第一个按钮时执行此操作。
正如你所说,问题是在执行
canvas
指令时,小部件的大小和位置是其初始默认值。在 python 中定义画布指令不会设置任何绑定,以便在小部件大小和/或位置发生变化时对这些 canvas
指令进行调整。解决此问题的一种方法是设置这些绑定,如下所示:
def on_btn_release(self):
wid = Widget()
wid.size_hint = (1, 1)
with wid.canvas:
Color(rgb=(1, 0, 0))
Rectangle(size=wid.size, pos=wid.pos)
wid.bind(size=self.wid_changed)
wid.bind(pos=self.wid_changed)
self.root.add_widget(wid, 1)
def wid_changed(self, wid, new_attr):
wid.canvas.clear()
with wid.canvas:
Color(rgb=(1, 0, 0))
Rectangle(size=wid.size, pos=wid.pos)
您还可以使用
kv
中定义 canvas
指令的规则定义自定义小部件,以便 kv
为您设置绑定。