Search code examples
pythonkivykivy-language

How can I display the new value made by input for the next screen in Kivy


I have been trying to make this code work. Im using ScreenManager to manage my screen. I want the Input I entered on the first screen to be displayed the next screen. But instead, it just shows the initial value, and it doesn't change to the Inputted value.

Here is the Code i have done

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

Builder.load_string("""
<MenuScreen>:
    promptObject: prompts
    
    BoxLayout:
        orientation: 'horizontal'
        TextInput:
            id: prompts
            pos: 20,20
        Button:
            text: "Enter Prompt"
            pos: 30,30
            size: 100, 30
            on_press: root.submit()


<Newscreen>
    BoxLayout:
        orientation: 'vertical'
        TextInput:
            id: display_output
            text: root.output
            readonly: True

""")

class MenuScreen(Screen):
    promptObject = ObjectProperty()
    prompt = ''

    def submit(self):
            prompt = self.promptObject.text
            
            global result
            result = prompt
            
            sm.add_widget(NewScreen(name="Settings"))
            sm.switch_to(sm.get_screen("Settings"))
            NewScreen.display(self)
            
class NewScreen(Screen):
    output = "testing testing"
    def display(self):
        self.output = result
        print(result) #To test if it works
        
class TestApp(App):
    def build(self):
        global sm
        sm = ScreenManager()
        sm.add_widget(MenuScreen(name='menu'))
        return sm

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

I'm also thinking if i can instead Declare the Layout for the second screen later right before i call for the next Screen. Maybe that could work but if you have other method, it would be nice to see it.


Solution

  • thank you for the concise single-file example. this is a very helpful way to submit a kivy question. I have modified and tested the below app with various changes.

    I changed the root.submit to app.submit. This is not strictly required, it is just a choice in this example to put the logic in the main app. it is also possible to use root.submit and put the logic in the widget but one would have to pass a reference to the screen manager into that widget in that case.

    imported TextInput object instead of using ObjectProperty. when using an IDE it is helpful to declare objects with the specific type because it enables auto-complete

    assigned the ScreenManager to self.sm so this object is available throughout the app.

    finally, got rid of any reference to global. I think it is better to avoid use of this keyword and explicitly create the variable at the highest level where you need it and pass the value into the objects requiring it.

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    # from kivy.properties import ObjectProperty
    from kivy.uix.textinput import TextInput
    from kivy.properties import StringProperty
    from kivy.clock import Clock
    
    Builder.load_string("""
    <MenuScreen>:
        promptObject: prompts
    
        BoxLayout:
            orientation: 'horizontal'
            TextInput:
                id: prompts
                pos: 20,20
            Button:
                text: "Enter Prompt"
                pos: 30,30
                size: 100, 30
                on_press: app.submit()
    
    
    <Newscreen>
        BoxLayout:
            orientation: 'vertical'
            TextInput:
                id: display_output
                text: root.output
                readonly: True
    
    """)
    
    
    class MenuScreen(Screen):
        promptObject = TextInput()
    
    
    class NewScreen(Screen):
        output = StringProperty()
    
        def __init__(self, **kw):
            super().__init__(**kw)
    
        def display(self, result):
            # set the string property equal to the value you sent
            self.output = result
            print(result)  # To test if it works
    
    
    class TestApp(App):
    
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            # create screen manager with self so that you have access
            # anywhere inside the App
            self.sm = ScreenManager()
            # create the main screen
            self.menu_screen = MenuScreen(name='menu')
    
            # this could be deferred, or created at initialization
            self.settings_screen = NewScreen(name='Settings')
    
        #
        def submit(self):
            prompt = self.menu_screen.promptObject.text
            result = prompt
    
            # optional, deferred creation
            # self.settings_screen = NewScreen(name='Settings')
    
            # add to the screen manager
            self.sm.add_widget(self.settings_screen)
            # enter the value into your other screen
            self.settings_screen.display(result)
    
            # switch to this screen
            self.sm.current="Settings"
    
        def build(self) -> ScreenManager:
            # could create this screen right away, depending...
            # self.sm.add_widget(self.settings_screen)
            # of course you need the main screen
            self.sm.add_widget(self.menu_screen)
            # redundant, unless you create all screens at the beginning
            self.sm.current = 'menu'
            return self.sm
    
    
    if __name__ == '__main__':
        TestApp().run()