在初始化方法中使用控件相对坐标绘制线条

1 投票
2 回答
717 浏览
提问于 2025-04-18 15:37

我想在一个小部件(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 个回答

0

这是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

绑定前|绑定后:

绑定前 绑定后

2

我想避免使用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语言,它会自动为你创建绑定,不需要额外的语法。

撰写回答