用自定义宽度动画 Kivy Bezier 曲线? 有点傻的问题

问题描述

更新:和其他人讨论后,我认为这是一个有点愚蠢的问题。我想为改变宽度的贝塞尔曲线设置动画,但它没有宽度属性。使用 Line Bezier,我可以更改宽度,但无法设置动画。


我无法像 witdh 那样改变 BezierLine 曲线。
这是代码

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

class MyLayout(Widget):
    def __init__(self):
        super(MyLayout,self).__init__()
        with self.canvas:
            self.L=Bezier(points=[200,450,500,300,600,150],width=12)
            self.k=Line  (bezier=[100,350,400,200,50 ],width=12)

class MyApp(App):
    def __init__(self):
        super(MyApp,self).__init__()
    def build(self):
        return MyLayout()

if __name__=="__main__":
    MyApp().run()

输出

MyApp

问题是,

上面的曲线不是 width=12

我认为这是因为 Kivy 的 Bezier 类没有属性 width 因为当我在 kv lang 上执行它时,它给了我 AttributeError: 'kivy.graphics.vertex_instructions.Bezier' object has no attribute 'width'。那么,为什么不将 Linebezier 一起使用?我想在它上面使用 Animation,当我尝试在 Linebezier 上使用时,我得到 AttributeError: attribute 'bezier' of 'kivy.graphics.vertex_instructions.Line' objects is not readable

所以问题,

如何更改 widthBezier。如果不可能,有什么办法可以找到给定 x 的 cruve(或 ys)的 y,这样我就可以将 Ellipse在这些点上并调整它们的大小以模拟宽度?

谢谢并原谅我的英语

解决方法

Bezier 没有 width 属性,但 Line 有。因此,您可以为该 width 设置动画。一个简单的方法是通过动画一个 NumericProperty 来保持宽度。这是您的代码的修改版本:

from kivy.animation import Animation
from kivy.app import App
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.uix.widget import Widget
from kivy.graphics import *

class MyLayout(Widget):
    line_width = NumericProperty(12)
    def __init__(self):
        super(MyLayout,self).__init__()
        with self.canvas:
            self.L=Bezier(points=[200,450,500,300,600,150],width=self.line_width)
            self.k=Line  (bezier=[100,350,400,200,50 ],width=self.line_width)

    def on_line_width(self,instance,new_width):
        self.k.width = new_width

class MyApp(App):

    def build(self):
        Clock.schedule_once(self.anim)
        return MyLayout()

    def anim(self,dt):
        a = Animation(line_width=3)
        a.start(self.root)

if __name__=="__main__":
    MyApp().run()

如果您在 Line 中构建 kv,那么您甚至不需要 on_line_width() 方法,因为 kivy 会为您进行绑定。

,

该行可以使用bezier:,例如:

Line:
    bezier:[n1,n2,n3,n4]
    width:3

这是一个 Line,不是一个 Bezier,但你得到相同的结果...

一个例子:

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout

posicao=[]
class Draw(BoxLayout):
    def __init__(self,**kwargs):
        super(Draw,self).__init__(**kwargs)
    
    def on_touch_down(self,touch):
        posicao.append(touch.pos)
        
    def on_touch_up(self,touch):
        posicao.clear()
        
    def on_touch_move(self,touch):
        Line = Builder.load_string(
"""
FloatLayout:
    canvas:
        Color:
            rgba:11,.1,1,1
        Line:
            points: {pos}
            width:14
""".format(pos=(touch.pos,posicao[0])))
        self.add_widget(Line)
        posicao.clear()
        posicao.append(touch.pos)
        
class Code(App):
    def build(self):
        return Draw()
        
if __name__ == '__main__':
    Code().run()

我 或者:

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import *

posi = []

Builder.load_string(
"""
<Draw>:
    
""")
class Draw(BoxLayout):
    def __init__(self,touch):
        posi.clear()
        posi.append(touch.pos)
        
    def on_touch_up(self,touch):
        posi.clear()
        
    def on_touch_move(self,touch):
        with self.canvas:
            Line(points=[posi[0],touch.pos],width=14)
        posi.clear()
        posi.append(touch.pos)
            
class Code(App):
    def build(self):
        return Draw()
        
if __name__ == '__main__':
    Code().run()