我试图通过使用一个名为 "level "的数字属性改变画布圆线的角度来周期性地运行动画,因此它每秒钟都会通过创建一个时钟对象来刷新,但动画根本无法运行。另一方面,当用户在文本输入中输入'r'时,我也从.kv文件中调用了一个不同的方法,使 "level "数字属性产生动画,动画完美地运行。我不明白这是怎么回事,有谁能给我一些启示,我到底做错了什么?
请注意,这个动画影响了我的.kv文件中 "转速表 "注释部分下的id为 "仪表和针 "的部件。
import kivy
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.properties import *
from kivy.animation import Animation
import kivy.graphics
from kivy.clock import Clock
from math import cos, sin, pi
from functools import partial
import random
def rpm_conversion(rpm):
return (rpm * (180.5/8000) -135.5)
####################################################
#---------------------- GUI -----------------------#
class DataWindow(GridLayout):
def rpmupdate(self,dt):
rand = random.randint(0,8000)
gaugranim = Animation(level = rpm_conversion(float(rand)))
print("Timer triggered: " + str(self.level))
self.rpm = int(rand)
gaugranim.start(self)
def on_enter(self, value):
print(value[5:] )
self.display.text = "ecu> "
rand = random.randint(0,8000)
if(value[5:] == "r"):
anim = Animation(level = rpm_conversion(float(rand)) )
print("User triggered: " + str(self.level))
self.rpm = int(rand)
anim.start(self)
#Keeps user from deleting name in console
def bashlook(self,value, crs):
if(value[:5] != 'ecu> '):
self.display.text = "ecu> "
class OpensecuApp(App):
def build(self):
clock = DataWindow()
Clock.schedule_interval(clock.rpmupdate, 2)
return DataWindow()
if __name__ == '__main__':
OpensecuApp().run()
.kv:
#:import math math
[GaugeNumber@Label]:
text: str(ctx.i)
pos_hint: {"center_x": 0.5+0.42*math.sin(math.pi/8*(ctx.i-6)), "center_y": 0.5+0.42*math.cos(math.pi/8*(ctx.i-6))}
font_size: self.height/24
<DataWindow>:
id: opensecu
display: cmd
level: -135
rpm: 0
# Main window
rows:2
spacing: 10
padding: 10
canvas:
Color:
rgba: 0.1,0.1,0.1,1
Rectangle:
pos: self.pos
size: self.size
##########################################################
GridLayout:
size_hint: 1,1
cols: 3
#-------------------------- Data -----------------------------#
#Data
BoxLayout:
canvas:
Color:
rgba: 0.12,0.1195,0.122,1
Rectangle:
pos: self.pos
size: self.size
Label:
text: "I'm label 1"
#---------------------- Tachometer RPM ------------------------#
BoxLayout:
size_hint: 1.5,1
canvas.before:
Color:
rgba: 0.12,0.1195,0.122,1
Rectangle:
pos: self.pos
size: self.size
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
FloatLayout: #gauges numers
size_hint:None,None
size: (min(self.parent.size) * 0.95 ) , (min(self.parent.size) * 0.95 )
GaugeNumber:
i: 0
GaugeNumber:
i: 1
GaugeNumber:
i: 2
GaugeNumber:
i: 3
GaugeNumber:
i: 4
GaugeNumber:
i: 5
GaugeNumber:
i: 6
GaugeNumber:
i: 7
GaugeNumber:
i: 8
AnchorLayout: #gauges dots
anchor_x: 'center'
anchor_y: 'center'
size_hint:None,None
size: (min(self.parent.size) * 0.68 ) , (min(self.parent.size) * 0.68 )
Image:
source: "resources/gauge.png"
size: self.texture_size
AnchorLayout: #gauges level rail
anchor_x: 'center'
anchor_y: 'center'
canvas.before:
Color:
rgba: 0.1,0.1,0.1,1
Line:
width: min(self.size)/15
circle:
(self.center_x, self.center_y, min(self.width, self.height)
/ 2, -135.5, 45, 500)
cap: 'none'
size_hint:None,None
size: (min(self.parent.size) * 0.5 ) , (min(self.parent.size) * 0.5 )
AnchorLayout: #gauge's levels
id: gauge
anchor_x: 'center'
anchor_y: 'center'
canvas.before:
Color:
rgba: 0,0.93,1,0.5
Line:
width: min(self.size)/15
circle:
(self.center_x, self.center_y, min(self.width, self.height)
/ 2, -135, root.level , 50)
cap: 'none'
size_hint:None,None
size: (min(self.parent.size) * 0.5 ) , (min(self.parent.size) * 0.5 )
AnchorLayout: #blue line in gauge
anchor_x: 'center'
anchor_y: 'center'
canvas.before:
Color:
rgba: 0,0.93,1,0.5
Line:
width: min(self.width, self.height) / 100
circle:
(self.center_x, self.center_y, min(self.width, self.height)
/ 2, 0, 360 , 50)
cap: 'none'
size_hint:None,None
size: (min(self.parent.size) * 0.38 ) , (min(self.parent.size) * 0.38 )
BoxLayout: #gauge real time RPMS
size_hint:None,None
size: (min(self.parent.size) * 0.38 ) , ((min(self.parent.size) * 0.38) )
Label:
text: str(int(root.rpm))
pos_hint: {"center_x": 0.5, "center_y": 0.65}
font_size: self.height / 6
BoxLayout:#gauges RPM note
size_hint:None,None
size: (min(self.parent.size) * 0.38 ) , ((min(self.parent.size) * 0.38) )
Label:
text: "RMP"
pos_hint: {"center_x": 0.5, "center_y": 0.35}
font_size: self.height / 12
BoxLayout:#gauges x1000
size_hint:None,None
size: (min(self.parent.size) * 0.38 ) , ((min(self.parent.size) * 0.38) )
Label:
text: "x1000"
pos_hint: {"center_x": 0.5, "center_y": 0.25}
font_size: self.height / 10
FloatLayout: #gauges needle
id: needle
anchor_x: 'center'
anchor_y: 'center'
size_hint:None,None
size: (min(self.parent.size) * 0.60 ) , (min(self.parent.size) * 0.60 )
Image:
source: "resources/needle.png"
size: self.texture_size
pos_hint: {'center_x': .5, 'center_y': .5}
canvas.before:
PushMatrix
Rotate:
angle: (root.level)* (-1)
origin: self.center
canvas.after:
PopMatrix
#------------------------ Volumetric Efficiency Table -------------------------#
BoxLayout:
canvas:
Color:
rgba: 0.12,0.1195,0.122,1
Rectangle:
pos: self.pos
size: self.size
Label:
text: "I'm label 3"
###################################################################
#------------------------ Console -------------------------#
BoxLayout:
size_hint: 1,0.3
canvas:
Color:
rgba: 0.12,0.1195,0.122,1
Rectangle:
pos: self.pos
size: self.size
TextInput:
id: cmd
text: "ecu> "
background_color: 0.12,0.1195,0.122,1
foreground_color: 1,1,1,1
boold: 1
padding: 15
multiline: False
on_text: opensecu.bashlook(self.text, self.cursor)
on_text_validate: opensecu.on_enter(self.text)
# on_key_down:opensecu.on_enter(self.text)
我找到的解决方案是创建对象属性,这样我就可以为每个我需要添加动画的widget拥有特定的自定义属性。
python:
import kivy
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.textinput import TextInput
from kivy.properties import *
from kivy.animation import *
import kivy.graphics
from kivy.clock import Clock
from math import cos, sin, pi
from functools import partial
import random
def rpm_conversion(rpm):
return (rpm * (180.5/8000) -135.5)
####################################################
#---------------------- GUI -----------------------#
class Gaugenumber(Label)
class OpensecuGauge(AnchorLayout):
gauge_level = NumericProperty(-135)
def gauge_anim(self,dt):
anim = Animation(gauge_level = rpm_conversion(float(readings[0])), d=0.5 )
anim.start(self)
class OpensecuNeedle(Image):
needle_level = NumericProperty(-135)
def needle_anim(self,dt):
# print(level)
anim = Animation(needle_level = rpm_conversion(float(readings[0])) , d=0.5)
anim.start(self)
class OpensecuWindow(GridLayout):
gauge = ObjectProperty(None)
needle = ObjectProperty(None)
def start(self):
Clock.schedule_interval(self.gauge.gauge_anim, 0.5)
Clock.schedule_interval(self.needle.needle_anim, 0.5)
Clock.schedule_interval(self.rpm_update, 0.5)
def rpm_update(self,dt):
anim = Animation(rpm = float(readings[0]), d=0.5)
anim.start(self)
def on_enter(self, value):
print(value[5:] )
self.display.text = "ecu> "
rand = random.randint(0,8000)
# print(self.gauge.level)
if(value[5:] == "r"):
pass
elif(value[5:]=="connect"):
cnnct()
self.start()
elif(value[5:]=="exit"):
stp()
else:
pass
#Keeps user from deleting name in console
def bashlook(self,value, crs):
if(value[:5] != 'ecu> '):
self.display.text = "ecu> "
class OpensecuApp(App):
def build(self):
# clock = OpensecuWindow()
# Clock.schedule_interval(clock.gauge.rpmupdate, 2)
connection = OpensecuWindow()
connection.start()
return OpensecuWindow()
if __name__ == '__main__':
OpensecuApp().run()
exit()
.kv:
#:import math math
[GaugeNumber@Label]:
text: str(ctx.i)
pos_hint: {"center_x": 0.5+0.42*math.sin(math.pi/8*(ctx.i-6)), "center_y": 0.5+0.42*math.cos(math.pi/8*(ctx.i-6))}
font_size: self.height/24
<OpensecuGauge>:
anchor_x: 'center'
anchor_y: 'center'
size_hint:None,None
<OpensecuNeedle>:
source: "resources/needle.png"
size: self.texture_size
pos_hint: {'center_x': .5, 'center_y': .5}
canvas.after:
PopMatrix
<OpensecuWindow>:
id: opensecu
display: cmd
needle: needle
gauge: gauge
# level: -135
# needle_level: -135
rpm: 0
# Main windows
rows:2
spacing: 10
padding: 10
canvas:
Color:
rgba: 0.1,0.1,0.1,1
Rectangle:
pos: self.pos
size: self.size
##########################################################
GridLayout:
size_hint: 1,1
cols: 3
#-------------------------- Data -----------------------------#
#Data
BoxLayout:
canvas:
Color:
rgba: 0.12,0.1195,0.122,1
Rectangle:
pos: self.pos
size: self.size
Label:
text: "I'm label 1"
#---------------------- Tachometer RPM ------------------------#
BoxLayout:
size_hint: 1.5,1
canvas.before:
Color:
rgba: 0.12,0.1195,0.122,1
Rectangle:
pos: self.pos
size: self.size
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
FloatLayout: #gauges numers
size_hint:None,None
size: (min(self.parent.size) * 0.95 ) , (min(self.parent.size) * 0.95 )
GaugeNumber:
i: 0
GaugeNumber:
i: 1
GaugeNumber:
i: 2
GaugeNumber:
i: 3
GaugeNumber:
i: 4
GaugeNumber:
i: 5
GaugeNumber:
i: 6
GaugeNumber:
i: 7
GaugeNumber:
i: 8
AnchorLayout: #gauges dots
anchor_x: 'center'
anchor_y: 'center'
size_hint:None,None
size: (min(self.parent.size) * 0.68 ) , (min(self.parent.size) * 0.68 )
Image:
source: "resources/gauge.png"
size: self.texture_size
OpensecuGauge: #gauges level rail
canvas.before:
Color:
rgba: 0.1,0.1,0.1,1
Line:
width: min(self.size)/15
circle:
(self.center_x, self.center_y, min(self.width, self.height)
/ 2, -135.5, 45, 500)
cap: 'none'
size: (min(self.parent.size) * 0.5 ) , (min(self.parent.size) * 0.5 )
OpensecuGauge: #gauges levels
id: gauge
canvas.before:
Color:
rgba: 0,0.93,1,0.5
Line:
width: min(self.size)/15
circle:
(self.center_x, self.center_y, min(self.width, self.height)
/ 2, -135, self.gauge_level , 50)
cap: 'none'
size: (min(self.parent.size) * 0.5 ) , (min(self.parent.size) * 0.5 )
AnchorLayout: #blue line in gauge
anchor_x: 'center'
anchor_y: 'center'
canvas.before:
Color:
rgba: 0,0.93,1,0.5
Line:
width: min(self.width, self.height) / 100
circle:
(self.center_x, self.center_y, min(self.width, self.height)
/ 2, 0, 360 , 50)
cap: 'none'
size_hint:None,None
size: (min(self.parent.size) * 0.38 ) , (min(self.parent.size) * 0.38 )
BoxLayout: #gauge real time RPMS
size_hint:None,None
size: (min(self.parent.size) * 0.38 ) , ((min(self.parent.size) * 0.38) )
Label:
text: str(int(root.rpm))
pos_hint: {"center_x": 0.5, "center_y": 0.65}
font_size: self.height / 6
BoxLayout:#gauges RPM note
size_hint:None,None
size: (min(self.parent.size) * 0.38 ) , ((min(self.parent.size) * 0.38) )
Label:
text: "RMP"
pos_hint: {"center_x": 0.5, "center_y": 0.35}
font_size: self.height / 12
BoxLayout:#gauges x1000
size_hint:None,None
size: (min(self.parent.size) * 0.38 ) , ((min(self.parent.size) * 0.38) )
Label:
text: "x1000"
pos_hint: {"center_x": 0.5, "center_y": 0.25}
font_size: self.height / 10
FloatLayout: #gauges needle
anchor_x: 'center'
anchor_y: 'center'
size_hint:None,None
size: (min(self.parent.size) * 0.60 ) , (min(self.parent.size) * 0.60 )
OpensecuNeedle:
id: needle
canvas.before:
PushMatrix
Rotate:
angle: (self.needle_level)* (-1)
origin: self.center
#------------------------ Volumetric Efficiency Table -------------------------#
BoxLayout:
canvas:
Color:
rgba: 0.12,0.1195,0.122,1
Rectangle:
pos: self.pos
size: self.size
Label:
text: "I'm label 3"
###################################################################
#------------------------ Console -------------------------#
BoxLayout:
size_hint: 1,0.3
canvas:
Color:
rgba: 0.12,0.1195,0.122,1
Rectangle:
pos: self.pos
size: self.size
TextInput:
id: cmd
text: "ecu> "
background_color: 0.12,0.1195,0.122,1
foreground_color: 1,1,1,1
boold: 1
padding: 15
multiline: False
on_text: opensecu.bashlook(self.text, self.cursor)
on_text_validate: opensecu.on_enter(self.text)
# on_key_down:opensecu.on_enter(self.text)