Search code examples
pythonkivykivy-languagekivymd

How to require a button to be clicked on the first tab before going to other tabs in Kivy/KivyMD


The code below is a demo I wrote. What I want to accomplish is that I have to click the button in the first tab before using other tabs. If the button is not clicked and I try to go to other tabs, a message will be shown and I'll be lead to the first tab. The problem is that the message will be shown, but I have to click one more time to go back to the first tab. Any idea how to fix it? Thanks in advance!

enter image description here

from kivy.lang import Builder

from kivymd.app import MDApp
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.button import MDRaisedButton
from kivymd.uix.tab import MDTabsBase
from kivymd.toast import toast


KV = '''
MDBoxLayout:
    orientation: "vertical"

    MDToolbar:
        title: "Example Tabs"

    MDTabs:
        id: tabs
        on_tab_switch: app.on_tab_switch(*args)


<Tab>

    MDLabel:
        id: label
        text: "Tab 0"
        halign: "center"

<Tab4test>
    MDLabel:
        id: label
        text: "Tab 0"
        halign: "center"        
    MDRaisedButton: 
        text: "Click me!!!"
        on_release: root.change_flag()
'''


class Tab(MDFloatLayout, MDTabsBase):
    '''Class implementing content for a tab.'''

class Tab4test(MDFloatLayout, MDTabsBase):
    '''Class implementing content for a tab.'''
    def change_flag(self):
        MDApp.get_running_app().flag =1
        toast("flag value changed to 1!")

class Example(MDApp):
    flag = 0
    def build(self):
        return Builder.load_string(KV)

    def on_start(self):
        self.root.ids.tabs.add_widget(Tab4test(title=f"Tab 0"))
        for i in range(1, 3):
            self.root.ids.tabs.add_widget(Tab(title=f"Tab {i}"))
        print(self.flag)

    def on_tab_switch(
        self, instance_tabs, instance_tab, instance_tab_label, tab_text
    ):
        '''Called when switching tabs.

        :type instance_tabs: <kivymd.uix.tab.MDTabs object>;
        :param instance_tab: <__main__.Tab object>;
        :param instance_tab_label: <kivymd.uix.tab.MDTabsLabel object>;
        :param tab_text: text or name icon of tab;
        '''

        instance_tab.ids.label.text = tab_text
        print(self.flag)
        title = instance_tab.title

        if title != f"Tab 0" and self.flag == 0:
            toast("Please click the button in Tab 0 first!", duration=3)
            #print(instance_tabs.carousel.slides)
            #instance_tabs.carousel.load_slide(instance_tabs.carousel.slides[0])
            instance_tabs.switch_tab("Tab 0", search_by="title")

Example().run()

Solution

  • After searching what's inside of this MDTabs, I found MDTabsBar and i decited to disabled this on opening. After clicking button on first tab, i activate it:

    test.py:

    from kivymd.app import MDApp
    from kivymd.uix.floatlayout import MDFloatLayout
    from kivymd.uix.tab import MDTabsBase
    from kivy.uix.screenmanager import Screen,ScreenManager
    from kivy.properties import StringProperty,ObjectProperty
    from kivy.clock import Clock
    class S1(Screen):
        mdtabs= ObjectProperty()
        def on_enter(self, *args):
            Clock.schedule_once(self.settings)
        def settings(self,*args):
            print(self.mdtabs.children[0])
            self.mdtabs.children[0].disabled = True
        def fu(self):
            self.mdtabs.children[0].disabled = False
    class SM(ScreenManager):
        pass
    class Tab(MDFloatLayout, MDTabsBase):
        pass
    class test(MDApp):
        def build(self):
            return SM()
    if __name__ == '__main__':
        test().run()
    

    test.kv:

    <SM>:
        S1:
            name: 'p1'
    <S1>:
        mdtabs:mdtabs
        MDTabs:
            id: mdtabs
            Tab:
                title: 'Tab1'
                Button:
                    text: 'Click me'
                    on_release: root.fu()
            Tab:
                title: 'Tab2'