[英]Rotate image in Kivy without using Builder / .kv file and NumericProperty
因此,基於許多不同的示例,我將示例Kivy應用程序拼湊在一起,該應用程序使用Kivy Animation
旋轉圖像。
我想知道如何在不使用.kv
文件(或Builder.load_string
)的情況下實現相同的結果。
#! /usr/bin/env python3
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Rectangle, Color, Rotate, PushMatrix, PopMatrix
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.graphics.svg import Svg
from kivy.animation import Animation
from kivy.lang import Builder
from kivy.properties import NumericProperty
import random
WINDOW_WIDTH, WINDOW_HEIGHT = Window.size
Builder.load_string('''
<Sprite>:
canvas.before:
PushMatrix
Rotate:
angle: self.angle
axis: (0, 0, 1)
origin: self.center
canvas.after:
PopMatrix
''')
class Sprite( Image ):
angle = NumericProperty(0)
def __init__( self, x=0, y=0, **kwargs ):
super( Sprite, self ).__init__( **kwargs )
self.size_hint = (None, None) # tell the layout not to size me
self.angle = 0
self.source = 'alien.png'
self.size = self.texture.size
if ( x == 0 and y == 0 ):
self.pos = ( random.randrange(0,WINDOW_WIDTH) , random.randrange(0,WINDOW_HEIGHT) )
else:
self.pos = ( x,y )
self.animate() # start moving animation
def animateComplete( self, *kargs ):
Animation.cancel_all( self ) # is this needed?
self.angle = 0
self.animate()
def animate( self ):
self.anim = Animation( angle=360, duration=1 )
self.anim.bind( on_complete=self.animateComplete )
self.anim.repeat = True
self.anim.start( self )
class FPSText( Label ):
def __init__( self, **kwargs ):
super( FPSText, self ).__init__( **kwargs )
self.size_hint = (None, None) # tell the layout not to size me
self.pos_hint = { 'right':1, 'top':1 }
def update( self, count ):
self.text = "%d aliens / %3.1f FPS" % ( count, Clock.get_fps() )
self.size = self.texture_size
class AlienGame( FloatLayout ):
def __init__(self, **kwargs):
super( AlienGame, self).__init__(**kwargs)
self.aliens = []
self.fps_text = FPSText()
self.add_widget( self.fps_text )
self.addAlien( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 )
def addAlien( self, x=0, y=0 ):
new_alien = Sprite( x, y )
self.aliens.append( new_alien )
self.add_widget( new_alien )
def update( self, dt ):
self.fps_text.text = '--'
self.fps_text.update( len( self.aliens ) )
def on_touch_down( self, touch ):
if ( touch.is_double_tap ):
for i in range( 7 ):
self.addAlien()
else: #if ( touch.is_single_tap ): (no single tap property)
self.addAlien( touch.pos[0], touch.pos[1] )
class RotApp( App ):
def build( self ):
game = AlienGame()
Clock.schedule_interval(game.update, 1.0 / 60.0)
return game
if ( __name__ == '__main__' ):
RotApp().run()
我嘗試了類似的東西:
class Sprite( Image ):
def __init__( self, x=0, y=0, **kwargs ):
super( Sprite, self ).__init__( **kwargs )
self.size_hint = (None, None) # tell the layout not to size me
self.source = 'alien.png'
self.size = self.texture.size
# define the rotation
with self.canvas.before:
PushMatrix()
self.rot = Rotate()
self.rot.angle = 0
self.rot.origin = self.center
self.rot.axis = (0, 0, 1)
with self.canvas.after:
PopMatrix()
但是無法獲取self.rot.angle
來更新動畫。 如果我手動處理動畫,效果很好,但是我想使用Kivy Animation
對象。
是否有執行此操作的純Python方法?
是的,有可能,這是您的Sprite類,僅使用python代碼進行旋轉。 這里唯一的是-制作kv lang是有原因的! 它使這些工作變得容易得多。 我強烈建議保留kv代碼。無論如何,要回答您的問題:關鍵是1)在self.rot小部件而不是self小部件上啟動動畫2)從self.center開始重置self.rot.origin變量是(0,0)初始化小部件的時間(在將其實際放置在屏幕上之前,為其賦予適當的self.center)。
另外,您可以使用bind
方法。 例如,設置self.rot.angle = self.angle
,然后設置self.rot.angle = self.angle
self.bind(angle=on_angle)
, on_angle
self.angle
更改,它將調用on_angle
函數。 您將必須定義一個self.on_angle
函數,該函數應重置self.rot.angle = self.angle
。 KV lang自動為您執行此操作,從而節省了大量代碼。 在kv中, angle: self.angle
每當self.angle
變量更改時angle: self.angle
自動更新angle
變量,這意味着不使用bind
函數。
這是您的Sprite類別。 注意兩行self.rot.origin = self.center
和self.anim.start(self.rot)
:
class Sprite( Image ):
angle = NumericProperty(0)
def __init__( self, x=0, y=0, **kwargs ):
super( Sprite, self ).__init__( **kwargs )
# define the rotation
with self.canvas.before:
PushMatrix()
self.rot = Rotate()
self.rot.angle = 0
self.rot.origin = self.center
self.rot.axis = (0, 0, 1)
with self.canvas.after:
PopMatrix()
self.size_hint = (None, None) # tell the layout not to size me
self.angle = 0
self.source = 'alien.png'
self.size = self.texture.size
if ( x == 0 and y == 0 ):
self.pos = ( random.randrange(0,WINDOW_WIDTH) , random.randrange(0,WINDOW_HEIGHT) )
else:
self.pos = ( x,y )
self.rot.origin = self.center # Reset the center of the Rotate canvas instruction
self.animate() # start moving animation
def animateComplete( self, *kargs ):
Animation.cancel_all( self ) # is this needed?
self.rot.angle = 0
self.animate()
def animate( self ):
self.anim = Animation( angle=360, duration=1 )
self.anim.bind( on_complete=self.animateComplete )
self.anim.repeat = True
self.anim.start( self.rot ) # Start rotating the self.rot widget instead of the self widget
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.