2

I have a data structure in the form of an object that I am representing graphically using Kivy.

If possible, I would like to write it so that when the root object is changed, the widgets in Kivy reflect the change. So far what I've noticed is that I can call on the object from the KV language when the widgets are initially created, and I can have those widgets modify the root object, but widgets that should be "bound" to the root object variables do not get updated.

I'm looking to find a way to "bind" them so that I don't have to write a "refresh/reload" function that loops through my data object each time a change is made.

Below is sample code that shows how I have my code set up so far.

From what I understood in the kivy api docs, using ObjectProperty(object, rebind=True) should be doing what I am trying to have done.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty


class DataObject():
    def __init__(self, name="foo", data="bar"):
        self.name = name
        self.data = data


class MainWindow(Screen):
    pass


class WindowManager(ScreenManager):
    data = DataObject()
    data_obj = ObjectProperty(data, rebind=True)


kv = Builder.load_file("my.kv")


class MyMainApp(App):
    def build(self):
        return kv


if __name__ == '__main__':
    MyMainApp().run()
WindowManager:
    MainWindow:


<MainWindow>:
    name: "Main"

    GridLayout:
        cols: 1

        GridLayout:
            cols: 2

            Label:
                text: root.manager.data_obj.name

        Button:
            text: "Change Name"
            on_release:
                root.manager.data_obj.name = "Bar"
                print(root.manager.data_obj.name)

Pressing the Button "Change Name" changes the object data_obj.name from "foo" to "bar" and prints that to the console confirming it changed

I would expect the Label text to also change to "bar"

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Will
  • 23
  • 2

1 Answers1

0

rebind works for Properties, and not for class attributes so your logic fails. One possible solution is that DataObject is an EventDispatcher and name, data is ObjectProperty:

from kivy.event import EventDispatcher

class DataObject(EventDispatcher):
    name  = ObjectProperty("foo")
    data = ObjectProperty("bar")
eyllanesc
  • 235,170
  • 19
  • 170
  • 241