Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement request: MDTabs 2.0.1 - added 2 examples #1658

Open
RobertFlatt opened this issue Mar 25, 2024 · 5 comments
Open

Enhancement request: MDTabs 2.0.1 - added 2 examples #1658

RobertFlatt opened this issue Mar 25, 2024 · 5 comments
Labels
Status: Needs analysis Issue needs to be analyzed if it's real Type: Bug Bug report/Bug fix

Comments

@RobertFlatt
Copy link

Description of the Feature

I wish to do lazy loading of MDTabsPrimary tabs and tab content with KivyMD 2.X , because the data displayed comes from some server.
Of course I assume I must statically define at least one tab and its contents.

I would like

  1. a method to append a new tab (and it's contents) at any time step.
  2. a method to replace the content of any existing tab at any time step.

I was able implement lazy loading of tabs with KivyMD 1.X

Thanks for your time, I think version 2 is great.

@HeaTTheatR
Copy link
Member

Thank you. Do you have any problems implementing this or can we close this issue?

@RobertFlatt
Copy link
Author

I can add tabs (but not their content), and I have a problem adding or changing Tab content. I think the issue is a different time step to that in which the MDTabsPrimary was instantiated.

I expect I can workaround by rebuilding the MDTabsPrimary as each tab contents arrives, but there will a (triangular) performance hit due to re-building tab contents on each new tab content. 8 tabs would be a total of 36 tab contents builds.

So I'd like an enhancement, the importance of dynamic loading of hidden tab contents in the context of your project as a whole is yours to prioritize.

Thanks for your time.

@RobertFlatt
Copy link
Author

@HeaTTheatR

I tried my assumed workaround, dynamically rebuilding (in Python) both MDTabsPrimary, and also just its children. I ran into problems with tab event scheduling:

   File "C:\Users\Bobf\AppData\Local\Programs\Python\Python311\Lib\site-packages\kivymd\uix\tab\tab.py", line 1241, in <lambda>
     lambda x: self._tabs_carousel.current_slide.tab_item.dispatch(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 AttributeError: 'MDLabel' object has no attribute 'tab_item' 

This MDLabel instance is the replaced tab content.

For the moment I'm out of ideas, so I would like to leave the issue open.

@HeaTTheatR HeaTTheatR added the Status: Needs analysis Issue needs to be analyzed if it's real label Mar 26, 2024
@HeaTTheatR
Copy link
Member

Okay, thanks for the analysis. I'll check it out...

@RobertFlatt
Copy link
Author

RobertFlatt commented Apr 3, 2024

@HeaTTheatR

Two Examples of changing Content at a later time step.
The first example is appending the second example is replacing

  1. Adding more tabs and content at a later time step.
    The tabs are added but the new content is the content of the previous last tab.
from kivy.lang import Builder
from kivy.clock import Clock

from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.tab import (
    MDTabsItemIcon,
    MDTabsItemText,
    MDTabsItem,
)

KV = '''
MDScreen:
    md_bg_color: self.theme_cls.backgroundColor

    MDTabsPrimary:
        id: tabs
        pos_hint: {"center_x": .5, "center_y": .5}
        size_hint_x: .6

        MDDivider:

        MDTabsCarousel:
            id: related_content_container
            size_hint_y: None
            height: dp(320)
'''


class Example(MDApp):
    def on_start(self):
        super().on_start()
        self.add_tabs(["Flights","Trips","Explore"])
        Clock.schedule_once(self.more_tabs, 2)

    def more_tabs(self,dt):
        #### These tabs are added, but not the contents
        self.add_tabs(["Dogs","Cats","Snakes"])

    def add_tabs(self, names):
        for tab_name in names:
            self.root.ids.tabs.add_widget(
                MDTabsItem(
                    MDTabsItemText(
                        text=tab_name,
                    ),
                )
            )
            self.root.ids.related_content_container.add_widget(
                MDLabel(
                    text=tab_name,
                    halign="center",
                )
            )
            self.root.ids.tabs.switch_tab(icon="airplane")

    def build(self):
        self.theme_cls.primary_palette = "Olive"
        return Builder.load_string(KV)


Example().run()

=====================================================================
2) Replacing the contents of existing tabs at a later time step.
Works, but crashes on subsequent tab change initiated by clicking tab:

   File "C:\Users\Bobf\AppData\Local\Programs\Python\Python311\Lib\site-packages\kivy\uix\carousel.py", line 295, in load_slide
     start, stop = slides.index(self.current_slide), slides.index(slide)

Or with swipe:

   File "C:\Users\Bobf\AppData\Local\Programs\Python\Python311\Lib\site-packages\kivymd\uix\tab\tab.py", line 1034, in android_animation
     a = instance.current_slide.tab_item
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 AttributeError: 'MDLabel' object has no attribute 'tab_item'
from kivy.lang import Builder
from kivy.clock import Clock

from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.tab import (
    MDTabsItemIcon,
    MDTabsItemText,
    MDTabsItem,
)

KV = '''
MDScreen:
    md_bg_color: self.theme_cls.backgroundColor

    MDTabsPrimary:
        id: tabs
        pos_hint: {"center_x": .5, "center_y": .5}
        size_hint_x: .6

        MDDivider:

        MDTabsCarousel:
            id: related_content_container
            size_hint_y: None
            height: dp(320)
'''


class Example(MDApp):
    def on_start(self):
        super().on_start()
        self.add_tabs(["Flights","Trips","Explore"])
        # Works, but crashes on tab change.
        Clock.schedule_once(self.replace_tab_content, 2)

    def replace_tab_content(self,dt):
        new_content = ["peace","love","understanding"]
        container = self.root.ids.related_content_container
        container.clear_widgets()
        for content in new_content:
            container.add_widget(
                MDLabel(
                    text=content,
                    halign="center",
                )
            )
        

    def add_tabs(self, names):
        for tab_name in names:
            self.root.ids.tabs.add_widget(
                MDTabsItem(
                    MDTabsItemText(
                        text=tab_name,
                    ),
                )
            )
            self.root.ids.related_content_container.add_widget(
                MDLabel(
                    text=tab_name,
                    halign="center",
                )
            )
            self.root.ids.tabs.switch_tab(icon="airplane")

    def build(self):
        self.theme_cls.primary_palette = "Olive"
        return Builder.load_string(KV)


Example().run()


@RobertFlatt RobertFlatt changed the title Enhancement request: MDTabs 2.0.1 Enhancement request: MDTabs 2.0.1 - added 2 examples Apr 3, 2024
@HeaTTheatR HeaTTheatR added the Type: Bug Bug report/Bug fix label Apr 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Needs analysis Issue needs to be analyzed if it's real Type: Bug Bug report/Bug fix
Projects
None yet
Development

No branches or pull requests

2 participants