ObjectProperty of ListProperty not updating

280 views
Skip to first unread message

Dylan Baker

unread,
Sep 17, 2019, 1:32:02 PM9/17/19
to Kivy users support
I have a ListProperty that I want to use in an intermediate, but I'm not seeing updates when I change the ObjectProperty version:

Here's some python code

from kivy.app import App
from kivy.properties import (
    ListProperty,
    ObjectProperty,
)
from kivy.uix.screenmanager import Screen, ScreenManager


class Manager(ScreenManager):
    pass


class MainScreen(Screen):

    state = ObjectProperty()


class TestApp(App):

    state = ListProperty([])

    def build(self):
        return Manager()


if __name__ == '__main__':
    TestApp().run()


And some .kv:

<MainScreen>:
    name: 'mainscreen'
    state: app.state
    BoxLayout:
        Label:
            text: "len: {}".format(len(root.state))
        Button:
            text: "test"
            on_release: root.state.append(0)


<Manager>:
    MainScreen:


I would expect when I push the "test" button that the label would increment in value, since the list is getting bigger. I can see that hte list is increasing in size by adding a "print()" to the on_release. Is this a bug or am I doing something wrong?

Alexander Taylor

unread,
Sep 17, 2019, 3:39:42 PM9/17/19
to Kivy users support
At a quick look, it's probably because the ObjectProperty triggers events only when the object it holds changes, it doesn't know about internal changes in the object. Try using a ListProperty instead.

Elliot Garbus

unread,
Sep 17, 2019, 4:29:24 PM9/17/19
to kivy-...@googlegroups.com

It’s not clear to me what you are trying to achive.

 

You have MainScreen.state declared in 2 places:

class MainScreen(Screen):
    state = ObjectProperty()  # This is declaring root.state

is redundant with:

<MainScreen>:
    state: app.state  # this is declaring root.state, and initializing it to the value in app.state

 

If you comment out

  # state: app.state

 

And make the object property a list property

class MainScreen(Screen):
    state = ListProperty()  # This is declaring root.state



Then the test will behave as expected.

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/53ddd8de-b07b-4bb0-a39d-6ddf7ed0948e%40googlegroups.com.

 

Dylan Baker

unread,
Sep 17, 2019, 5:17:41 PM9/17/19
to Kivy users support
What I want is to have the MainScreen be able to modify the app.state variable, and reflect those changes.

using an ObjectProperty the app.state changes, but the MainScreen isn't updated to reflect those changes. Using a ListProperty the MainScreen.state is updated, but because it's a copy the state in App.state is not updated. I guess I could have an `on_state` event that would synchronize them.

Obviously this is a minimal example, but in a real application I want to store my state in a single place, and have multiple screens view and act on that data.

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-...@googlegroups.com.

Elliot Garbus

unread,
Sep 17, 2019, 6:40:23 PM9/17/19
to kivy-...@googlegroups.com

You can access app variables from anywhere in KV by referring to them as:

app.name

 

inside python you can use the App method get_running_app() to access them.

 

def my_code():

    app_ptr = App.get_running_app()

    app_ptr.name = ‘I am writing this string to  app.name

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/bd8df852-e0fe-4d10-9ef0-47bbbca1360e%40googlegroups.com.

 

Dylan Baker

unread,
Sep 17, 2019, 7:08:39 PM9/17/19
to Kivy users support
Okay, one more question. Am I fighting kivy's architecture structuring my app this way?

Elliot Garbus

unread,
Sep 17, 2019, 7:37:44 PM9/17/19
to kivy-...@googlegroups.com

I don’t think I know enough about your apps structure, but in general no, I don’t think you are fighting kivy’s architecture.

 

Kivy is object oriented, occasionally you will have challenges on how to access data between classes.  Using properties or variables in App, is a reasonable solution.

 

The widget tree also provides a rich syntax for reaching across objects and screens.

Here is a line from a piece of code I’m working on:

e = App.get_running_app().root.ids.sm.get_screen('editor').ids.editor
  • sm is a screenmanager
  • ‘editor’ is a screen
  • editor is an id, in the instatce of the Editor() class that is displayed on the ‘editor’ screen.
  • I can then use e to access methods and points in the instance of the Editor class
    • e.method_name()  or access attributes e.attribute_name; from anywhere.

 

There is fantastic development/debug/kivy exploration tool called the inspector that is useful for exploring the widget tree.

 

From the command line: python your_main.py -m inspector

 

Read about it here: https://kivy.org/doc/stable/api-kivy.modules.html#module-kivy.modules

 

Hope this helps.  Kivy is a complex system, there is a learning curve, but also good docs.  If you have any questions don’t hesitate to post to the forum.

Good Luck!

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/f8f49adc-a816-4658-9651-50a74b794885%40googlegroups.com.

 

Dylan Baker

unread,
Sep 17, 2019, 10:15:46 PM9/17/19
to Kivy users support
Okay, that makes sense. thanks.
Reply all
Reply to author
Forward
0 new messages