Mit*_*ops 9 python layout user-interface kivy
我正在制作一个像大表盘一样旋转的圆圈.目前,我在顶部有一个箭头,显示表盘朝向哪个方向.我希望它的行为有点像一个老式的旋转手机,这样当你的手指/光标向下时你可以旋转它,但它会(放慢)在你松开后慢慢地回到顶部.
这是我的对象的样子:

这是我的代码:
#!/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()
Run Code Online (Sandbox Code Playgroud)
和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
Run Code Online (Sandbox Code Playgroud)
部分内容来自kivy touchtracer演示,以及SO问题.
你可以看到我的计算正确地打印了圆的原点和触摸事件之间的角度(不知道这对多个手指有什么反应,没想到那么远),但不知道如何整合这成为界面中的"旋转"反馈事件.
您可以将画布的角度绑定到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()
Run Code Online (Sandbox Code Playgroud)
我正在计算初始(按下鼠标后)和后来的角度之间的差异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()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5263 次 |
| 最近记录: |