pythonkivyscreen

How to refer on object


I want to select an object from a class Screen, while in App class.

I wrote a command that I want to execute, but it doesn't work in the code. I want the code to fire when the application is closed.

main.py:

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

class Screeen(Screen):
    pass

class Manager(ScreenManager):
    pass

kv = Builder.load_file("plann.kv")
class Ball(App):
    #def on_stop(self):
        #print(Screeen.ids.textinput.text)

    def build(self):
        return kv

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

plann.kv:

Manager:
    Screeen:

<Screeen>:
    name: "Screeen"
    textinput: textinput
    FloatLayout:
        size: root.width, root.height
        TextInput:
            id: textinput
            text: "hi"
            size_hint: (.45, .1)
            pos: root.width * 1 / 3 , root.height * 1 / 2

Solution

  • here is a tested and working example. The idea is to keep a reference to your top-level (root) widget in your init of the app so you can reference it later.

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    
    class Screeen(Screen):
        pass
    
    class Manager(ScreenManager):
        pass
    
    
    kv_string = '''
    Manager:
        Screeen:
    
    <Screeen>:
        name: "Screeen"
        textinput: textinput
        FloatLayout:
            size: root.width, root.height
            TextInput:
                id: textinput
                text: "hi"
                size_hint: (.45, .1)
                pos: root.width * 1 / 3 , root.height * 1 / 2
    '''
    
    class Ball(App):
        def on_stop(self):
            print(f"closing: {self.sm.current_screen.textinput.text}")
    
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            # type-hint will help the IDE guide you to methods, etc.
            self.sm: ScreenManager = Builder.load_string(kv_string)
    
        def build(self):
            # could add more screens here
            return self.sm
    
        def on_start(self):
            print(f"App Type is {type(self)}")
            print(f"sm type is {type(self.sm)}")
            print(f"root type is {type(self.root)}")
            print(f"current screen type {type(self.sm.current_screen)}")
            print(f"current screen {self.sm.current_screen}")
            print(f"{self.sm.current_screen.textinput.text}")
    
    
    if __name__ == "__main__":
        Ball().run()
    

    I changed the .kv file to a string just to make this an easier one-file test. The use of a .kv file is a good idea so you can just make that little adjustment in your project.