Kivy ObjectProperty 更新标签文本

2022-01-15 00:00:00 python kivy

问题描述

我正在创建一个 kivy 用户界面来显示由我作为标准 python 对象编写的数据模型生成的值.本质上,我希望用户能够按下一个按钮,这将改变底层数据模型,并且这种改变的结果将自动更新和显示.据我了解,这可以使用 kivy 属性(在本例中为 ObjectProperty)来实现.

I am working on creating a kivy user interface to display the values generated by a data model I've written as a standard python object. In essence, I would like the user to be able to press a button, which would change the underlying data model and the results of this change would be automatically updated and displayed. It is my understanding that this can be implemented using kivy properties (in this case, 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()

所需的结果是当用户按下任一按钮时,标签会自动更新以显示新属性.从打印语句可以看出,data_model 正在正确更新.但是,没有一个标签正在更新.有人可以澄清如何做到这一点吗?

The desired result is for when user presses either button, the labels would automatically update to show the new properties. As can be seen by the print statements, the data_model is getting updated correctly. However, none of the labels are updating. Can someone clarify how to do this?


解决方案

但是,所有标签都没有更新.有人可以澄清如何做到这一点吗?

However, none of the labels are updating. Can someone clarify how to do this?

你引用的属性需要是Kivy属性,但是你引用的abc都是python属性所以Kivy无法绑定到他们的更改.

The attributes you reference need to be Kivy properties, but the a, b and c you reference are all just python attributes so Kivy has no way to bind to their changes.

要使用属性,您需要您的对象从 EventDispatcher 继承(Kivy 小部件会自动执行此操作,这就是它们的属性起作用的原因).

To work with properties you need your object to inherit from EventDispatcher (Kivy widgets do this automatically, which is why their properties work).

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 以获得更类似于您的原始定义的内容.

Note that this is not the only way (or even necessarily the best way) to get the behaviour you wanted for c. You could create the binding in kv language (I'd usually do it that way) or you can look at Kivy's AliasProperty for something more like your original definition.

当然你也可以在声明属性时设置 a 和 b 的值.

Of course you could also set the values of a and b when the properties are declared.

相关文章