介绍
kivy.properties 模块提供了一种方便的方式来创建属性,并为这些属性添加验证和事件处理。在 Kivy 中,属性 (property) 是一种特殊的类成员,它们用于管理对象的状态和行为。然而其"properties" 通常可以翻译为"属性"或者"特性",这两个词都比较合适。它们指的是 Kivy 中用来描述组件的状态或者特征的变量或者属性。
模块
kivy.properties中的函数提供了丰富的功能,可以满足不同类型属性的定义和管理需求。通过合理使用这些类和函数,可以更好地开发 Kivy 应用程序,并实现属性的有效管理和控制,常见的函数如下:
- Property:定义属性的基类,用于创建各种类型的属性,例如 NumericProperty 和 StringProperty。
- BoundedNumericProperty:定义有界数值属性,可以指定最小值和最大值。
- AliasProperty:创建一个别名属性,可以通过计算或者其他方式动态生成属性值。
- ObjectProperty:定义对象类型的属性。
- ListProperty:定义列表类型的属性。
- DictProperty:定义字典类型的属性。
- BooleanProperty:定义布尔类型的属性。
- StringProperty:定义字符串类型的属性。
- NumericProperty:定义数值类型的属性。
- ReferenceListProperty:定义引用列表类型的属性。
- OptionProperty:定义选项类型的属性,值必须在指定的选项列表中选择。
用途
了解玩kivy.properties中的函数后,那我们就来尝试发掘一下这些函数都作何用途嘞。
声明属性
在如下代码中,我们实现了在类中声明属性,并在类外创建类的实例并访问属性与修改属性。
# 导入部件元素的基类
from kivy.uix.widget import Widget
# 导入属性管理类
from kivy.properties import NumericProperty, StringProperty
#创建玩家属性类
class 玩家属性(Widget):
# 声明玩家的名称
名称_1 = StringProperty('夕星')
# 声明玩家的等级
等级_1 = NumericProperty(10)
# 声明玩家的职业
职业_1 = StringProperty('刺客')
"""下文监听代码填写区域"""
"""手动监听代码填写区域"""
# 创建 玩家属性 实例
玩家属性 = 玩家属性()
# 访问和修改属性
print(f'名称:{玩家属性.名称_1} ')
print(f'等级:{玩家属性.等级_1} ')
print(f'职业:{玩家属性.职业_1} ')
# 修改名称属性的值
玩家属性.名称_1 = "夕星大魔王"
# 修改等级属性的值
玩家属性.等级_1 = 999
# 修改职业属性的值
玩家属性.职业_1 = '法师'
print(f'名称:{玩家属性.名称_1} ')
print(f'等级:{玩家属性.等级_1} ')
print(f'职业:{玩家属性.职业_1} ')
"""调用手动监听代码填写区域"""
那么当一个游戏的属性都创建后,如果实现类似于,玩家等级提升后,提示对应的语法逻辑嘞,比如提示“恭喜玩家成功提升到1000级,成为领先全球99.99%的无敌存在”。这里就需要监控逻辑嘞,那我们接着往下看怎么实现的。
监听属性变化
可以监听属性的变化,从而执行相应的代码,比如等级增加后的提示代码等
如下代码中,我们实现了对指定属性的监控,以及获取实例对象、变更属性对象,变更后的新值。
注意:监听属性函数的命名有规则,一般是on_+监听的属性名称。如下就是监听名称属性的示例。还有就是这个函数不需要调用,因为这是一个自动触发的方法,直接放在属性的类中就可以直接监控!
那么我们来思考一下,名称和职业属性应该如何监控嘞?
def on_等级(self, instance, value):
print(f'恭喜玩家成功提升到{value}级,成为领先全球99.99%的无敌存在')
绑定属性
可以将一个属性与另一个属性绑定,从而实现属性的同步更新,比如在游戏内的玩家等级属性可以分为大厅等级、个人主页等级,这里就可以用到绑定属性咯。
在如下的代码中通过在等级_1的触发事件给self.等级_2赋值,即可实现等级_2与等级_1同步更新。
def on_等级_1(self, instance, value):
print(f'恭喜玩家成功提升到{value}级,成为领先全球99.99%的无敌存在')
self.等级_2 = value
手动触发属性变化
可以通过手动的方式来触发自动函数,这里的手动也可以叫做调用。
在如下代码中,函数名的命名没有规则限制,其中重点代码是最后一行,最后一行接受两个参数。
第一个参数指定了监听的属性对象,第二个参数指定是是哪一个实例正在调用自动监听函数。
属性对象为等级_1,自动监听函数与此函数在同一个实例对象内,所以是self。
注意:当手动监听函数被触发后,自动监听函数是会被触发两次的,一次的手动触发函数发起的,一次的自动监听函数触发的
def 修改等级(self, new_value):
print("手动触发属性变化信号")
# 修改属性值
self.等级_1 = new_value
# 手动触发属性变化 property特性,dispatch发送信号
self.property('等级_1').dispatch(self)
"""这里忽略中间部分"""
# 调用手动监听函数
玩家属性.修改等级(15)
计算属性
通过创建别名属性,来实现属性的绑定,绑定的过程中可以自定义计算方式。比如要保持玩家_3的等级始终为玩家_2的两倍,这里用到AliasProperty来绑定在合适不过。
在如下代码中,我们实现了玩家_3的等级不论等级_2怎么变化,始终为其的两倍。其中,AliasProperty接受两个参数,参数一为绑定的计算值的函数,参数二为绑定的属性对象,示例中,绑定对象“等级_2”发生变化,等级三就会改变!
然而这个计算属性的函数,就是返回了等级_2的两倍的数值
def 计算属性(self):
return self.等级_2 * 2
等级_3 = AliasProperty(计算属性, bind=['等级_2'])
代码
# 导入部件元素的基类
from kivy.uix.widget import Widget
# 导入属性管理类
from kivy.properties import NumericProperty, StringProperty ,AliasProperty
#创建玩家属性类
class 玩家属性(Widget):
# def __init__(self, **kwargs):
# super(玩家属性, self).__init__(**kwargs)
# self.bind(等级_2=self.on_等级_1)
# 声明玩家的名称
名称_1 = StringProperty('夕星')
# 声明玩家的等级
等级_1 = NumericProperty(10)
# 声明玩家的职业
职业_1 = StringProperty('刺客')
def on_等级_1(self, instance, value):
print(f'恭喜玩家成功提升到{value}级,成为领先全球99.99%的无敌存在')
self.等级_2 = value
名称_2 = StringProperty('七星')
等级_2 = NumericProperty(20)
职业_2 = StringProperty('射手')
def 修改等级(self, new_value):
print("手动触发属性变化信号")
# 修改属性值
self.等级_1 = new_value
# 手动触发属性变化 property特性,dispatch发送信号
self.property('等级_1').dispatch(self)
名称_3 = StringProperty('鸡精')
# 等级_3 = NumericProperty(30)
职业_3 = StringProperty('法师')
def 计算属性(self):
print(f"等级2:{self.等级_2}")
return self.等级_2 * 10
等级_3 = AliasProperty(计算属性, bind=['等级_3'])
# 创建 玩家属性 实例
玩家属性 = 玩家属性()
print("\033[31m访问属性\033[0m")
# 访问和修改属性
print(f'名称:{玩家属性.名称_1} ')
print(f'等级:{玩家属性.等级_1} ')
print(f'职业:{玩家属性.职业_1} ')
# 修改名称属性的值
玩家属性.名称_1 = "夕星大魔王"
# 修改等级属性的值
玩家属性.等级_1 = 999
# 修改职业属性的值
玩家属性.职业_1 = '法师'
print("\033[31m修改属性\033[0m")
print(f'名称:{玩家属性.名称_1} ')
print(f'等级:{玩家属性.等级_1} ')
print(f'职业:{玩家属性.职业_1} ')
print("\033[31m手动触发监控属性函数\033[0m")
玩家属性.修改等级(15)
# 访问射手的属性
print(f'名称:{玩家属性.名称_2} ')
print(f'等级:{玩家属性.等级_2} ')
print(f'职业:{玩家属性.职业_2} ')
print("\033[31m计算属性\033[0m")
# 访问射手的属性
print(f'名称:{玩家属性.名称_3} ')
print(f'等级:{玩家属性.等级_3} ')
print(f'职业:{玩家属性.职业_3} ')
有待更新....