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
相关产品推荐
相关产品推荐

