在初始化方法中使用控件相对坐标绘制线条
我想在一个小部件(Widget)里面画一条线。但是我发现,直到初始化方法结束之前,这个小部件的相对位置和大小都还没有确定。
我该怎么做才能在创建这个类的时候,就在小部件里面画出一个图形元素,并且能够使用它的相对位置和尺寸呢?(我希望能避免使用Kv语言)
class Track(Widget):
def __init__(self,**kw):
super(Track, self).__init__(**kw)
with self.canvas:
Color(1,0,0)
Line(points = (self.x, (self.y + self.height) / 2, self.x + self.width, (self.y + self.height) / 2))
这样的话,画出的线是用初始的大小和位置,也就是100,100和0,0,但这个小部件是在一个布局里面,所以我想用相对位置和大小,并且希望能在初始化的时候就画出来。
2 个回答
这是Inclement给出的精彩答案的演示!
我们的目标是把一个图形重新放置到小部件的中心。
from kivy.app import App
from kivy.graphics.vertex_instructions import Line
class MyWidget(Widget):
def __init__(self):
super().__init__()
print(f"on init: {self.width}, {self.height}")
with self.canvas:
self.coordinate = Translate(0, 0)
Line(points=[0,0,100,100], width=20)
#Comment the following line
self.bind(pos=self.reposition, size=self.reposition)
def reposition(self, *args):
print(f"on reposition: {self.width}, {self.height}")
self.coordinate.xy = self.width/2, self.height/2
class myApp(App):
def build(self):
return MyWidget()
myApp().run()
结果:
on init: 100, 100
on reposition: 1000, 500
绑定前|绑定后:
我想避免使用Kv语言。
我建议你放弃这个限制。
这样的话,线条是根据初始的大小和位置绘制的,分别是100,100和0,0,但这个小部件是在一个布局里面,所以我想用相对的位置和大小,并且希望在初始化时绘制它。
你有三个选择。第一个选择是在一个时钟(kivy.clock.Clock
)的调度函数中绘制它,这个函数会在小部件被放置后运行。你只需要做 Clock.schedule_once(the_func, 0)
,其中的 0
表示在小部件放置后(假设布局正常)但在下一个帧之前再进行计算。缺点是,这条线就会固定住,如果小部件移动,比如在窗口调整大小时,线条就不会跟着移动了。
第二个(更好的)选择是像现在这样绘制线条,但绑定一个函数到小部件的位置和大小,这个函数会适当地重新放置线条。比如 self.bind(pos=self.line_setter, size=self.line_setter)
,然后让 self.line_setter
成为一个方法,里面有 self.line.points = [...]
这样的代码。你还需要保存线条的引用,使用 self.line = Line(...)
。
第三个(通常是最好的)选择是使用Kv语言,它会自动为你创建绑定,不需要额外的语法。