0

I am attempting to bind a method to the text value of a spinner. It needs to be bound no later than when the TestScreen is displayed. This works if I don't use the ScreenManager, (eg if TestApp.build returns TestScreen instead of TestScreenManager). When TestApp.build returns TestScreenManager I get the following error when I reference self.ids in TestScreen.__init__

AttributeError: 'super' object has no attribute '__getattr__'

Test.py

from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.app import App


class TestScreen(Screen):
    def __init__(self, *args, **kwargs):
        super(TestScreen, self).__init__(*args, **kwargs)
        self.ids.test_spinner.bind(text=self.on_spinner_select)

    def on_spinner_select(self, instance, data, *largs):
        print("In on_spinner_select")

    def print_spinner_value(self):
        print(self.ids.test_spinner.text)


class TestScreenManager(ScreenManager):
    pass


class TestApp(App):
    def build(self):
        #return TestScreen()
        return TestScreenManager()


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

Test.kv

<TestScreen>:
    name: "World Screen"

    BoxLayout:
        orientation: 'vertical'

        Label:
            text: "Name"
            font_size: 30

        BoxLayout:
            Label:
                text: "Active Selection"
                size_hint_x: .5

            Spinner:
                id: test_spinner
                text: "Value1"
                values: ["Value1", "Value2"]

        Button:
            text: "Print spinner value"
            on_press: root.print_spinner_value()


<TestScreenManager>:
    TestScreen:

I have tried binding the method in the on_enter method but I get the same error. However, self.ids does work in the method print_spinner_value if I comment out the self.ids statement in the init function.

Currently I was able to find a work around by binding the function every time the spinner is pressed. But that doesn't seem like the best way to handle the problem

on_press: self.bind(text=root.on_spinner_select)

So my question is: How do I bind a method to the spinner on load while using the ScreenManager?

jonyfries
  • 772
  • 6
  • 20
  • updated to include *args in the `__init__` function per suggestion below. This has the same results. – jonyfries Apr 20 '18 at 13:46
  • I see that this has been flagged as a duplicate - I disagree however as while the solution is the same the error being thrown is different. So a person with the error I received would not easily find the other post. – jonyfries Oct 29 '20 at 20:39

2 Answers2

1

I guess the init of your screen hasn't finished when you try to bind this method. Try this:

...
from kivy.clock import Clock
...
class TestScreen(Screen):
    def __init__(self, **kwargs):
        super(TestScreen, self).__init__(**kwargs)
        Clock.schedule_once(self.on_start)

    def on_start(self, *args):
        self.ids.test_spinner.bind(text=self.on_spinner_select)
Simon Mengong
  • 2,625
  • 10
  • 22
0

Try using __init__(self, *args, **kwargs). Using **kwargs only assumes that the input is always some sort of keyword argument (dicts, for instance). That's pretty much what the error means, as it is trying to bring all attributes from the argument that you passed.

ohduran
  • 787
  • 9
  • 15