Search code examples
pythonkivykivy-language

How to change label from another class in kivy?


My application has 2 windows. The second window has a label, and I want to change its text with the first window button. But every time I get the same error:

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

Here's my Python code:

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

class WindowManager(ScreenManager):
    pass

class FirstWindow(Screen):
    def change_label(self):
        self.parent.ids.label_id.text = 'label is changed'
        
class SecondWindow(Screen):
    pass

Builder.load_file('new.kv') 

class FirstApp(App): 
    def build(self):
        screen_manager = ScreenManager()
        screen_manager.add_widget(FirstWindow(name = 'first'))
        screen_manager.add_widget(SecondWindow(name = 'second'))
        return screen_manager

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

and my .kv file:

#:kivy 2.0.0

<FirstWindow>:
    name: "first"
    padding: 50
    spacing: 250

    BoxLayout:
        padding: 50
        spacing: 250
        orientation: 'vertical'  

        Button:
            text: 'change_label'
            pos_hint: {'center_x': 0.5, 'center_y': 0.15}
            on_release:
                root.change_label()
        
        Button:
            text: 'second window'
            pos_hint: {'center_x': 0.5, 'center_y': 0.15}
            on_release:
                root.manager.current = 'second'
                root.manager.transition.direction = 'left'
         
<SecondWindow>:
    name: 'second' 
    padding: 50
    spacing: 250
    label_id: label_id
   
    BoxLayout:
        padding: 50
        spacing: 50
        orientation: 'vertical'   

        Label:
            id: label_id
            text: 'this label'
   
        Button:
            text: 'first window'  
            on_release:
                app.root.current = "first" 
                root.manager.transition.direction = 'right' 

Solution

  • You just need to get a reference to the SecondWindow instance, and you can do that using the get_screen() method of the ScreenManager:

    class FirstWindow(Screen):
        def change_label(self):
            # self.parent.ids.label_id.text = 'label is changed'
            self.manager.get_screen('second').ids.label_id.text = 'label is changed'