You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy如何为不同Label设置同原点不同旋转角度实现幸运轮盘

问题根源

你之前的写法是把Rotate变换添加到了Day布局的全局画布上,属于父布局的全局变换,每次添加只会叠加整个布局的旋转效果,自然无法单独作用于单个Label,同时你也没有为每个标签计算独有的角度偏移,所有标签用了相同的角度值。

解决方案

写一个通用的单标签旋转容器类,在循环中为每个文本动态生成对应角度的容器实例即可,无需重复定义多个布局类。

修改后的完整代码

main.py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.properties import NumericProperty, ListProperty
from kivy.uix.label import Label
from kivy.graphics import PushMatrix, PopMatrix, Rotate
import math 

Builder.load_file("myy.kv")
am0=["Example1","Example2","Example3"] # 动态文本列表,可随意修改长度

class MainWidget(Widget):
    item_list = ListProperty(am0)
    pass

# 轮盘拖拽旋转逻辑保持不变,新增点击区域判断避免误触
class Cark(FloatLayout):
    angle = NumericProperty(0)

    def on_touch_down(self, touch):
        if not self.collide_point(*touch.pos):
            return super().on_touch_down(touch)
        y = (touch.y - self.center[1])
        x = (touch.x - self.center[0])
        calc = math.degrees(math.atan2(y, x))
        self.angle1 = calc if calc > 0 else 360+calc
        self.mvmt = self.angle
        return True

    def on_touch_move(self, touch):
        if not self.collide_point(*touch.pos):
            return super().on_touch_move(touch)
        y = (touch.y - self.center[1])
        x = (touch.x - self.center[0])
        calc = math.degrees(math.atan2(y, x))
        angle2 = calc if calc > 0 else 360+calc
        self.angle = self.mvmt + (angle2-self.angle1)%360
        return True

# 通用单标签旋转容器,接收文本和角度参数即可
class DayaItem(FloatLayout):
    def __init__(self, text, angle, **kwargs):
        super().__init__(**kwargs)
        b1 = Label(text=text, pos_hint={'center_x': .8, 'center_y': .5}, size_hint=(None, None))
        self.add_widget(b1)          
        with self.canvas.before:
            PushMatrix()
            self.rotation = Rotate()
            self.rotation.origin = self.center
            self.rotation.angle = angle
            self.bind(center=lambda _, value: setattr(self.rotation, "origin", value))            
        with self.canvas.after:
            PopMatrix()

# 动态生成所有标签的父容器
class Day(FloatLayout): 
    def __init__(self, item_list, **kwargs):
        super().__init__(**kwargs)
        step_angle = 360 / len(item_list)
        # 遍历文本列表,为每个文本生成对应角度的标签容器
        for idx, text in enumerate(item_list):
            current_angle = idx * step_angle
            self.add_widget(DayaItem(text=text, angle=current_angle))
    
    # 可选:动态更新文本列表的方法,数据源变化时调用即可
    def update_items(self, new_item_list):
        self.clear_widgets()
        step_angle = 360 / len(new_item_list)
        for idx, text in enumerate(new_item_list):
            current_angle = idx * step_angle
            self.add_widget(DayaItem(text=text, angle=current_angle))

class MyyApp(App):
    def build(self):
        return MainWidget()

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

myy.kv

<MainWidget>:
    cark:cark
    Cark:
        id: cark
        size: root.size
        pos: 0, 0
        canvas:
            Rotate:
                angle: self.angle
                origin: self.center
            Color:
                rgb: 1, 0, 0
            Ellipse:    
                size: min(self.size), min(self.size)
                pos: 0.5*self.size[0] - 0.5*min(self.size), 0.5*self.size[1] - 0.5*min(self.size)
        # 直接添加动态标签容器,传入文本列表即可
        Day:
            item_list: root.item_list

内容的提问来源于stack exchange,提问作者Batuhan Karakaya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 04:27:00