Kivy 中带有推送和弹出矩阵的多个自定义小部件

Multiple custom widgets with push and pop matrix in Kivy

我有以下用于自定义旋钮小部件的代码。我试图在一个布局中放置 6 个这样的旋钮。但是当我将kv代码包装到CustomKnob@BoxLayout中时它似乎不起作用,我遵循了这个。有没有办法复制 kv 代码以具有 6 个旋钮,每个旋钮都有自己的触摸区域?

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.graphics.context_instructions import PushMatrix, PopMatrix, Rotate
from kivy.lang import Builder
from kivy.properties import NumericProperty

import math

kv = '''
<Dial>
    canvas:
        PushMatrix 
        Rotate:
            angle: root.angle
            origin: self.center    
            
        # red circle        
        Color:
            rgb: 1,0,0            
        Line: 
            circle: (self.center_x, self.center_y, 112, 0, self.angle)
            width: 5
       
        #green circle        
        Color:
            rgb: .1, 1, .1
        Line:
            width: 2
            circle: (self.center_x, self.center_y, min(self.width, self.height)/ 8.5)
        PopMatrix
        
    Label:
        id: lbl
        text: str(round(root.angle/360,2))
        center: self.parent.center

'''
Builder.load_string(kv)


class Dial(Widget):

    angle = NumericProperty(90)

    def __init__(self, **kwargs):
        super(Dial, self).__init__(**kwargs)

    def on_touch_move(self, touch):
        y = (touch.y - self.center[1])
        x = (touch.x - self.center[0])
        temp_calc = math.degrees(math.atan2(y, x))
        if temp_calc >= 0:
            calc = temp_calc
        else:
            calc = 360 + temp_calc
        self.angle = calc
        print(round(self.angle / 360, 2))


class DialApp(App):
    def build(self):
        return Dial()


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

您可以在 kv 中为 CustomKnob 添加规则:

<CustomKnob@BoxLayout>:
    orientation: 'vertical'
    Dial:
        id: d1
    Dial:
        id: d2
    Dial:
        id: d3
    Dial:
        id: d4
    Dial:
        id: d5
    Dial:
        id: d6

然后,在您的 build() 方法中:

class DialApp(App):
    def build(self):
        return Factory.CustomKnob()

需要使用 Factory,因为 CustomKnobkv 中定义。

请注意,您仍然必须确定 Dials 的大小和位置。