我正在创建一个kivy用户界面来显示由我编写为标准python对象的数据模型生成的值。本质上,我希望用户能够按下一个按钮,这将改变底层数据模型,并且将自动更新和显示此更改的结果。我的理解是,这可以使用kivy属性(在本例中为ObjectProperty)来实现。
以下是一些示例代码:
import kivy
kivy.require('1.7.0')
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from kivy.lang import Builder
Builder.load_string("""
<RootWidget>:
cols: 2
Label:
text: "Attribute a:"
Label:
text: root.data_model.a
Label:
text: "Attribute b:"
Label:
text: root.data_model.b
Label:
text: "Attribute c:"
Label:
text: root.data_model.c
Button:
text: "Make data_model.a longer"
on_press: root.button_press()
Button:
text: "Make data_model.b shorter"
on_press: root.button_press2()
""")
class DataModel(object):
def __init__(self):
self.a = 'This is a'
self.b ='This is b'
@property
def c(self):
return self.a + ' and ' + self.b
class RootWidget(GridLayout):
data_model = ObjectProperty(DataModel())
def button_press(self, *args):
self.data_model.a = 'This is a and it is really long now'
print self.data_model.c
def button_press2(self, *args):
self.data_model.b = 'B'
print self.data_model.c
class TestApp(App):
def build(self):
return RootWidget()
app = TestApp()
app.run()
当用户按下任一按钮时,所需的结果是标签会自动更新以显示新属性。从print语句可以看出,data_model正在正确更新。但是,没有标签正在更新。有人可以澄清如何做到这一点吗?
答案 0 :(得分:6)
但是,没有标签正在更新。有人可以澄清如何做到这一点吗?
您引用的属性需要是Kivy属性,但您引用的a
,b
和c
都只是python属性,因此Kivy无法绑定到它们的更改。
要使用属性,您需要从EventDispatcher
继承对象(Kivy小部件会自动执行此操作,这就是它们的属性有效的原因)。
from kivy.event import EventDispatcher
class DataModel(EventDispatcher):
a = StringProperty('')
b = StringProperty('')
c = StringProperty('')
def __init__(self, *args, **kwargs):
super(DataModel, self).__init__(*args, **kwargs)
self.a = 'This is a'
self.b ='This is b'
self.bind(a=self.set_c)
self.bind(b=self.set_c)
def set_c(self, instance, value):
self.c = self.a + ' and ' + self.b
请注意,不是获得c所需行为的唯一方式(甚至是最好的方式)。你可以用kv语言创建绑定(我通常会这样做)或者你可以看看Kivy的AliasProperty更像你的原始定义。
当然,您还可以在声明属性时设置a和b的值。
答案 1 :(得分:3)
这是我的解决方案:
https://gist.github.com/jsexauer/8861079
本质上,我创建了一个包装数据模型和UI的包装类。有一些我不喜欢的东西,也许其他人可以改进:
__init__()
,而不是让它使用全局变量(因此是硬编码的)。我试图让它工作,但遇到了一个弱的递归地狱。也许对Python对象模型有更好理解的人可以实现这一点。