Search code examples
kivykivymd

How to disable a widget when a button from a different class is pressed?


Im making a Button which disables a TopAppBar menu form my user interface, the problem is that the Button is on one class an the TopAppBar in another, because one belongs to the screen and the other is shared between multiple screens.

code:

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivymd.uix.screen import MDScreen



Window.size = (300, 500)

navigation_helper = """


<UserScreen>

    name: 'user_screen'


    MDBoxLayout:
        orientation: "vertical"
        pos_hint: {"top": 1}
        adaptive_height: True
        padding: (0, "80dp" , 0, 0)
    
    
            
            
                
        FloatLayout:
        
            MDRaisedButton:
                id: save_btn_user
                text: "Guardar"
                md_bg_color: "white"
                text_color: "black"
                font_size: 16.2
                pos_hint: {"left":1, "bottom": 1}
                size_hint: (.2,.2)  
                disabled: True   
                on_press: root.save_btn_press()
            
                               
                
            MDRaisedButton:
                id: edit_btn_user
                text: "Editar"
                md_bg_color: "white"
                text_color: "black"
                font_size: 16.2
                pos_hint: {"right":1, "bottom": 1}
                size_hint: (.2,.2)  
                disabled: False
            
                on_press:        
                    root.disable_top_bar()







<MainScreen>:
    name: "main_screen"

    BoxLayout:
        orientation: 'vertical'
    
        MDTopAppBar:
            id: title_bar
            title: 'Dietas'
            md_bg_color: 0.08,0.07,0.45                     
            specific_text_color: 1,1,1
            left_action_items: [["menu", lambda x: nav_drawer.set_state('toggle')]]
        
        Widget:


    MDNavigationLayout:

        ScreenManager:
            id: scr
                    
            UserScreen:

        MDNavigationDrawer:
            id: nav_drawer
    
            BoxLayout:
                orientation: 'vertical'
                spacing: '8dp'
           
                ScrollView:
                    MDList:

                        OneLineIconListItem:
                            text: 'Usuario'
                            on_press: 
                                scr.current= 'user_screen'
                                title_bar.title = "Usuario"
                                nav_drawer.set_state('close')
                            IconLeftWidgetWithoutTouch:
                                icon: 'account'
                                on_press: 
                                    scr.current= 'user_screen'
                                    title_bar.title = "Usuario"
                                    nav_drawer.set_state('close')
                            
                   
                            
                    
                            
MainScreen:
"""



    
class UserScreen(MDScreen):



    def disable_top_bar(self):
        self.a=MainScreen()
        self.a.disable_top_barr()
    

class MainScreen(MDScreen):
    def disable_top_barr(self):
    
        self.ids.title_bar.disabled = True
        print("testmsg")
    
class DemoApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = ("Dark")
        screen = Builder.load_string(navigation_helper)
        return screen
       
            


DemoApp().run()

As you may have seen, I tried creating two method, one in the TopAppBar class disabling it and printing a test message(that its shown) and the other in the Button class calling that function.


Solution

  • With the following approach

        def disable_top_bar(self):
            self.a=MainScreen()
            self.a.disable_top_barr()
    

    you will see no change in your GUI because each time you call that method, it will create a new instance of MainScreen (which is not related to your GUI) and call the asked method on it.

    In order to access that specific instance you can use the method get_running_app of MDApp as follows,

        def disable_top_bar(self):
            # First access the running app instance.
            app = MDApp.get_running_app()
            # Access the target screen that you set as the root widget.
            main_screen =  app.root
            # Call the method.
            main_screen.disable_top_barr()
    

    As a note avoid using predefined names like a, b, g etc. when working with KivyMD widgets.