kivy

2013-12-09 25 views
9

Büyük bir arama gibi tür döneceği bir daire yapmaya çalışıyorum bir dokunmatik olay bir nesneyi döndürmek. Şu anda, kadranın hangi yöne baktığını göstermek için üstte bir ok var. Ben onun davranışı tür bir eski timey döner telefon gibi olmak istiyorum, parmak/imleç aşağı durumdayken döndürmek, ancak gitmesine izin sonra (yavaş yavaş) başa dön yank edeceğiz böyle. ödünç edilirkivy

#: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 

Parçalar:

#!/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() 

Ve kv:

enter image description here

Ve işte benim kod:

İşte böyle benim nesne nasıl göründüğü ve kivy touchtracer demosu ve from this SO question.

Dairenin kökeni ile dokunma olayı arasındaki açıyı doğru şekilde yazdıran bir hesaplama yaptığımı görebilirsiniz (bunun birden çok parmağa nasıl yanıt vereceğinden emin değilsiniz, çok uzak olduğunu düşünmeyin) Bunu arayüzde bir "iplik" geri bildirim olayıyla nasıl bütünleştireceğinizden emin olun.

cevap

4

Kodunuzdaki içinden değiştirmek için, NumericProperty için tuvalin açısını bağlayabilir. Tek yapmanız gereken bu açıları doğru bir şekilde hesaplamaktır. on_touch_move içinde

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() 

I (fare presleme işleminden sonra) Başlangıç ​​arasındaki farkın hesaplanması ediyorum ve daha sonra açı: onunla biraz oynama sonra aşağıdaki kodu oluşturulur. Açı bir özellik olduğundan, fare düğmesini bıraktıktan sonra çevirme dönüşü yapmak için kivy.animation'u kullanarak da değiştirebilirim. Çocuk çemberin

DÜZENLEME

on_touch_down olay:

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() 
+0

kopyalayabilirsiniz ::

pip install kivy-garden garden install geartick 

Çalışma Örneği yükleyin, ancak ben küçük daireye bir dokunuş olay eklemek nasıl biliyor musunuz tepede? Ben sadece ne yaptığımı bildiğimden emin olmak için bir on_touch ses etkinliği atandım, ya da ben/veya/çocuk çemberi için on_touch'a sahip olabilirim gibi görünüyor --- Görünüşe göre ikisine de sahip olamıyorum aynı zamanda. – Mittenchops

+0

'super' kullanarak' on_touch_down' olayını göndermelisiniz. Örneği ekledim. – Nykakin

+0

Her iki olayda da çift baskı var mı? – Mittenchops

3

Sen dönen kaymak bahçesinden GearTick kullanabilirsiniz. Tam olarak ihtiyacınız olan şey değil, ihtiyaçlarınız için uyarlanabilir. "Varsayılan olarak, saat yönünün tersine dönme olasılığınızın saat yönünde ilerlemesini sağlar" (Güncelle: Widget şimdi "saat yönünde" veya "saat yönünün tersine" olarak ayarlanabilen orientation özelliğine sahiptir).

Sen bahar sırt ve durdurma "parmak durağında" nde yönetmek gerekir

.

Uçtaki örnek, animasyonu kullanarak yayı tekrar yönetir, ancak yine de parmak durdurma işlevini yönetmeniz/uygulamanız gerekir.

https://github.com/kivy-garden/garden.geartick

Kullanımı ::

Python ::

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) 

enter image description here

için Eğer bu bu soru için kapsam dışında muhtemelen macunu ::

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) 
''')) 
+0

Çok güzel görünüyor, ancak modemi kurduktan sonra bile çalıştırmayı denediğimde, kivy.uix.behaviors import buttonBehavior ImportError: Hiçbir modül adlı davranış yok '' – Mittenchops

+0

Master'dan en son kivy'ye ihtiyacınız var . Buradan yükleme talimatlarına bakın http://kivy.org/docs/installation/installation.html#development-version –

+0

Hmm, garip, evet, master'dan yükledim ve hala şans yok. – Mittenchops