gpt4 book ai didi

python - 在 kivy 中的触摸事件上旋转对象

转载 作者:太空狗 更新时间:2023-10-29 20:22:59 25 4
gpt4 key购买 nike

我正在努力制作一个可以像大表盘一样旋转的圆圈。目前,我在顶部有一个箭头来显示表盘朝向哪个方向。我希望它的行为有点像老式的旋转电话,这样当你的手指/光标向下时你可以旋转它,但在你松开后它会(慢慢地)猛拉回顶部。

这是我的对象的样子:

enter image description here

这是我的代码:

#!/usr/bin/kivy
import kivy
kivy.require('1.7.2')
import math

from random import random
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.graphics import Color, Ellipse, Rectangle

class MinimalApp(App):
title = 'My App'
def build(self):
root = RootLayout()
return(root)

class RootLayout(AnchorLayout):
pass

class Circley(RelativeLayout):
angle = 0
def on_touch_down(self, touch):
ud = touch.ud
ud['group'] = g = str(touch.uid)
return True
def on_touch_move(self, touch):
ud = touch.ud
# print(touch.x, 0)
# print(self.center)
# print(0, touch.y)
# print(touch.x - self.center[0], touch.y - self.center[1])
y = (touch.y - self.center[1])
x = (touch.x - self.center[0])
calc = math.degrees(math.atan2(y,x))
angle = calc if calc > 0 else (360 + calc)
print(angle)
def on_touch_up(self, touch):
touch.ungrab(self)
ud = touch.ud
return True

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

和kv:

#:kivy 1.7.2
#:import kivy kivy

<RootLayout>:
anchor_x: 'center' # I think this /is/ centered
anchor_y: 'center'
canvas.before:
Color:
rgba: 0.4, 0.4, 0.4, 1
Rectangle:
pos: self.pos
size: self.size
Circley:
anchor_x: 'center' # this is /not/ centered.
anchor_y: 'center'
canvas.before:
PushMatrix
Color:
rgba: 0.94, 0.94, 0.94, 1
Rotate:
angle: self.angle
axis: 0, 0, 1
origin: self.center
Ellipse:
source: 'arrow.png'
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)
Label:
text: unicode(self.size) # this is /not/ appearing
color: 1,0,0,1
canvas.after:
PopMatrix

部分内容借自 kivy touchtracer 演示,以及 from this SO question .

你可以看到我有一个计算正确地打印了圆的原点和触摸事件之间的角度(不确定这将如何响应多个手指,还没想那么远),但不确定如何将其集成到界面中的“旋转”反馈事件中。

最佳答案

您可以将 Canvas 的角度绑定(bind)到 NumericProperty,以便从您的代码中更改它。您需要做的就是正确计算这些角度。玩了一下之后,我创建了以下代码:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.animation import Animation
from kivy.properties import NumericProperty

import math

kv = '''
<Dial>:
canvas:
Rotate:
angle: root.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)
Color:
rgb: 0, 0, 0
Ellipse:
size: 50, 50
pos: 0.5*root.size[0]-25, 0.9*root.size[1]-25
'''
Builder.load_string(kv)

class Dial(Widget):
angle = NumericProperty(0)

def on_touch_down(self, touch):
y = (touch.y - self.center[1])
x = (touch.x - self.center[0])
calc = math.degrees(math.atan2(y, x))
self.prev_angle = calc if calc > 0 else 360+calc
self.tmp = self.angle

def on_touch_move(self, touch):
y = (touch.y - self.center[1])
x = (touch.x - self.center[0])
calc = math.degrees(math.atan2(y, x))
new_angle = calc if calc > 0 else 360+calc

self.angle = self.tmp + (new_angle-self.prev_angle)%360

def on_touch_up(self, touch):
Animation(angle=0).start(self)

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

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

我正在计算 on_touch_move 中初始(按下鼠标后)和后来角度之间的差异。由于角度是一个属性,因此我还可以使用 kivy.animation 修改它,以便在释放鼠标按钮后使拨号盘旋转回来。

编辑

on_touch_down 子圈事件:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.animation import Animation
from kivy.properties import NumericProperty

import math

kv = '''
<Dial>:
circle_id: circle_id
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)
Circle:
id: circle_id
size_hint: 0, 0
size: 50, 50
pos: 0.5*root.size[0]-25, 0.9*root.size[1]-25
canvas:
Color:
rgb: 0, 1, 0
Ellipse:
size: 50, 50
pos: self.pos
'''
Builder.load_string(kv)

class Circle(Widget):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
print "small circle clicked"

class Dial(Widget):
angle = NumericProperty(0)

def on_touch_down(self, touch):
if not self.circle_id.collide_point(*touch.pos):
print "big circle clicked"

y = (touch.y - self.center[1])
x = (touch.x - self.center[0])
calc = math.degrees(math.atan2(y, x))
self.prev_angle = calc if calc > 0 else 360+calc
self.tmp = self.angle

return super(Dial, self).on_touch_down(touch) # dispatch touch event futher

def on_touch_move(self, touch):
y = (touch.y - self.center[1])
x = (touch.x - self.center[0])
calc = math.degrees(math.atan2(y, x))
new_angle = calc if calc > 0 else 360+calc

self.angle = self.tmp + (new_angle-self.prev_angle)%360

def on_touch_up(self, touch):
Animation(angle=0).start(self)


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

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

关于python - 在 kivy 中的触摸事件上旋转对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20461336/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com