【问题标题】:Center of Canvas in Python vs kivy languagePython 与 kivy 语言中的 Canvas 中心
【发布时间】:2019-10-23 19:56:31
【问题描述】:

我制作了一个简单的应用程序,我尝试在其中展示我的问题。当使用 python 在 kivy 中绘制一条线时(使用 with self.canvas 方法),这条线从 center_x 和 center_y 为 50 绘制。

使用 kivy Lang 在中心正确绘制线。下面是一个简单的代码示例:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Line


class TestWidget(Widget):

    def draw(self):
        with self.canvas:
            Line(points=[self.center_x,self.center_y,self.center_x,self.center_y+100], width=2)


class TestApp(App):

    def build(self):
        test = TestWidget()
        test.draw()
        return test


if __name__ == '__main__':
    TestApp().run()

以及对应的test.kv文件:

#:kivy 1.11.1

<TestWidget>:
    canvas:      
        Line:
            width: 5
            points: (self.center_x,self.center_y,self.center_x,self.center_y+100)

结果是这样的:

知道为什么使用 python 代码不起作用吗?

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    这两个代码是不等价的,在python的情况下,您只是确定该行的位置基于当时小部件的中心,即在开头,而不是在.kv中表示线的位置总是相对于 Widget 的中心。

    TL;博士;

    说明:

    在kv中,绑定是一个自然而隐含的过程,在python中没有这样做,除了它的实现更简单,例如以下代码:

    Foo:
        property_i: other_object.property_j
    

    在这种情况下,它在 python 中的等价物是:

    foo = ...
    other_object = ...
    other_object.bind(property_j=foo.setter("property_i"))
    

    事实并非如此:

    foo.property_i = other_object.property_j
    

    由于使用绑定,您在更改property_j 之前使用该值更新property_i,但在最后的代码中,您此时仅指示将property_j 的值复制到property_i 中。

    在您的特定情况下,您采用的中心是在显示小部件之前,kivy 会考虑默认配置和其他属性,在小部件显示后更改其几何形状。

    解决方案

    根据前面的解释进行必要的修改,下面的代码等效于 .kv 代码

    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.graphics import Line
    
    
    class TestWidget(Widget):
        def __init__(self, **kwargs):
            super(TestWidget, self).__init__(**kwargs)
            with self.canvas:
                self.line = Line(width=2)
            self.bind(center=lambda *args: self.draw())
    
        def draw(self):
            self.line.points = [
                self.center_x,
                self.center_y,
                self.center_x,
                self.center_y + 100,
            ]
    
    
    class TestApp(App):
        def build(self):
            test = TestWidget()
            return test
    
    
    if __name__ == "__main__":
        TestApp().run()
    

    【讨论】:

      【解决方案2】:

      使用 kv 语言,您的声明会在它们的依赖关系发生变化时自动更新。这意味着当小部件的中心从 (50, 50) 变为其他位置时,该线将在新位置重绘。

      您的 Python 代码不会这样做,它只是使用代码运行时的中心点画线一次。该值为 (50, 50),因为这是定位之前的默认值。

      解决方案是用 Python 编写代码,当小部件中心发生变化时更新该行,类似于用 self.line = Line(...)self.bind(centre=some_function_that_updates_self_dot_line) 声明该行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-16
        相关资源
        最近更新 更多