Search code examples
pythonkivykivy-languagekivymd

How to change text from TextInput that is in another class/Screen?


I reproduced in these files the situation I have here.

I have two screens, I'm using ScreenManager and what I want is, when I click on the button "Generate Evidence" that, instead of printing on the console, what I pass as a parameter is printed on the other screen ('Running', where there is only a TextInput). But it's not changing the text on the other screen, I would like to know if this is possible and why it doesn't work this way. Thanks in advance.

mainApp.py

from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.app import MDApp


class Manager(ScreenManager):
    def __init__(self):
        super(ScreenManager, self).__init__()


class ScreenMain(Screen):
    def __init__(self, **kwargs):
        super(ScreenMain, self).__init__(**kwargs)

    # This is called when you click the button
    # Then the screen is changed
    # Then call this other function that is down there
    def change_text(self):
        self.manager.current = 'Running'
        print_whatever_is_happening()


# Second screen
class ScreenRunning(Screen):
    def __init__(self, **kwargs):
        super(ScreenRunning, self).__init__(**kwargs)

    def write_message_on_text_input(self, message):
        self.ids.data_log.text += message


class Example(MDApp):
    def build(self):
        sm = ScreenManager()
        self.running_screen = ScreenRunning(name='Running')
        self.main_screen = ScreenMain(name='ScreenMain')
        sm.add_widget(self.running_screen)
        sm.add_widget(self.main_screen)
        sm.current = 'ScreenMain'
        return sm


# This function is originally in a module, that's why it's outside the class
def print_whatever_is_happening():
    # Instead of this...
    print('Attaching 1')
    print('Attaching 2')
    print('Generating PDF file')
    print('Attaching file')

    # I would like to do this
    ScreenRunning().write_message_on_text_input('Attaching 1')
    ScreenRunning().write_message_on_text_input('Attaching 2')
    ScreenRunning().write_message_on_text_input('Generating PDF file')
    ScreenRunning().write_message_on_text_input('Attaching file')


Example().run()

example.kv

<Manager>:
    id: screen_manager

    screen_main: screen_main
    screen_running: screen_running

    ScreenMain:
        id: screen_main
        name: 'ScreenMain'
        manager: screen_manager

    ScreenRunning:
        id: screen_running
        name: 'Running'
        manager: screen_manager

<ScreenMain>:
    BoxLayout
        id: Screen_One
        orientation: 'vertical'
        padding: '15dp'
        canvas:
            Color:
                rgb: 0.878, 0.8, 0.984, 1
            Rectangle:
                size: self.size
                pos: self.pos
        MDRoundFlatIconButton:
            id: evidence_button
            text: 'Generate Evidence'
            font_size: '17dp'
            text_color: 1, 1, 1, 1
            md_bg_color: 0.4, 0, 0.922, 1
            on_press: root.manager.get_screen('ScreenMain').change_text()


<ScreenRunning>:
    BoxLayout:
        orientation: 'vertical'
        padding: '15dp'
        canvas:
            Color:
                rgb: 0.878, 0.8, 0.984, 1
            Rectangle:
                size: self.size
                pos: self.pos

        TextInput:
            id: data_log
            multiline: True
            text: ''

Solution

  • You can use MDApp.get_running_app() to get a reference to your App, then use root to get the root of the App (which is the ScreenManager. Then you can use the get_screen() method to get a reference to the ScreenRunning instance. Using this approach, your print_whatever_is_happening() method can be:

    def print_whatever_is_happening():
        # Instead of this...
        print('Attaching 1')
        print('Attaching 2')
        print('Generating PDF file')
        print('Attaching file')
    
        # I would like to do this
        screenRunning = MDApp.get_running_app().root.get_screen('Running')
        screenRunning.write_message_on_text_input('Attaching 1')
        screenRunning.write_message_on_text_input('Attaching 2')
        screenRunning.write_message_on_text_input('Generating PDF file')
        screenRunning.write_message_on_text_input('Attaching file')