Te recomendamos que revises esta resolución en un entorno controlado antes de enviarlo a producción, un saludo.
Solución:
Puede enlazar el ángulo del lienzo a NumericProperty
, para cambiarlo desde dentro de su código. Todo lo que necesitas hacer es calcular esos ángulos correctamente. Después de jugar un poco con él, creé el siguiente código:
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 = '''
:
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()
Estoy calculando la diferencia entre el ángulo inicial (después de presionar el mouse) y el ángulo posterior en on_touch_move
. Dado que el ángulo es una propiedad, también puedo modificarlo usando kivy.animation
para hacer que el dial gire hacia atrás después de soltar el botón del mouse.
EDITAR
on_touch_down
evento para círculo infantil:
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 = '''
:
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()
Puede usar GearTick desde el jardín, que es un control deslizante giratorio. No es exactamente lo que necesita, pero se puede adaptar a sus necesidades. “De forma predeterminada, permite la rotación en el sentido contrario a las agujas del reloj, probablemente lo necesitaría en el sentido de las agujas del reloj” (Actualización: el widget ahora tiene un orientation
propiedad que se puede establecer en ‘sentido horario’ o ‘antihorario’).
Debería manejar el resorte hacia atrás y detenerse en el “tope del dedo”.
El ejemplo en los extremos maneja el spring back usando animación, sin embargo, aún necesita administrar / implementar la funcionalidad de detención del dedo.
https://github.com/kivy-garden/garden.geartick
Uso::
Pitón::
from kivy.garden.geartick import GearTick
parent.add_widget(GearTick(range=(0, 100)))
kv ::
BoxLayout:
orientation: 'vertical'
GearTick:
id: gear_tick
zoom_factor: 1.1
# uncomment the following to use non default values
#max: 100
#background_image: 'background.png'
#overlay_image: 'gear.png'
#orientation: 'anti-clockwise'
on_release:
Animation.stop_all(self)
Animation(value=0).start(self)
Label:
size_hint: 1, None
height: '22dp'
color: 0, 1, 0, 1
text: ('value: ').format(gear_tick.value)
Instalar::
pip install kivy-garden
garden install geartick
Ejemplo de trabajo que puede copiar y pegar:
from kivy.lang import Builder
from kivy.app import runTouchApp
from kivy.garden.geartick import GearTick
runTouchApp(Builder.load_string('''
#:import Animation kivy.animation.Animation
GridLayout:
cols: 2
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
orientation: 'vertical'
GearTick:
id: gear_tick
zoom_factor: 1.1
# uncomment the following to use non default values
#max: 100
#background_image: 'background.png'
#overlay_image: 'gear.png'
#orientation: 'anti-clockwise'
on_release:
Animation.stop_all(self)
Animation(value=0).start(self)
Label:
size_hint: 1, None
height: '22dp'
color: 0, 1, 0, 1
text: ('value: ').format(gear_tick.value)
'''))
Sección de Reseñas y Valoraciones
Si eres capaz, tienes la habilidad dejar un ensayo acerca de qué te ha parecido este escrito.