更新label tex的Kivy ObjectProperty

2024-05-15 20:32:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在创建一个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语句可以看出,数据模型得到了正确的更新。但是,没有一个标签正在更新。有人能解释一下怎么做吗?


Tags: textfromimportselfdatamodelisdef
2条回答

以下是我的解决方案:

https://gist.github.com/jsexauer/8861079

实际上,我创建了一个包装类,它连接数据模型和UI。有几件事我不喜欢,也许其他人可以改进:

  • 任何更新底层数据模型的UI函数都必须用UI_data model类提供的“update”装饰器进行装饰。最好不要包含decorator,尽管我不确定如何在不实质性修改data model类工作方式的情况下这样做(但这一点的关键是,您不应该接触底层数据模型类)
  • 我希望能够将公共数据模型实例传递给UI数据模型的__init__(),而不是让它使用全局变量(因此是硬编码的)。我试着让这个工作,但遇到了一个可怕的递归地狱。也许对Python对象模型有更好理解的人可以实现这一点。

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

您引用的属性必须是Kivy属性,但是您引用的abc都只是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的值。

相关问题 更多 >