Search code examples
pythonkivykivy-language

Getting widget/item ids within TabbedPanel


I have created a simple App in Kivy that has tabs and within each tab I only have a few widgets. Prior to adding the tabbedPanel I had no issue reaching each widget through "ids". For example:

app.root.ids.mylabel1.ids.mylabel2.content

However, now that I have added widgets within the tabbedPanel they become unreachable for me. The tabbedPanel "blocks" me and contains no ids: For example my .kv-file has a button:

<SelectableButton>:
    text: self.button_text
    id: SelectableButton_id
    canvas.before:
        Color:
            rgba: (0, 0.517, 0.705, 1) if self.selected else (0, 0.517, 0.705, 1)
        Rectangle:
            pos: self.pos
            size: self.size
    state: self.btnState
    on_release:
        print(app.root.content.ids)

returns an empty dict. I followed the guidance for tabbedPanel and found that it only has one "children" which is ".content". But still I am not able to reach any widgets within this tab.

Am I going about this the wrong way? Or can anyone guide me to how to access the widgets within a certain tab.


Solution

  • With Kivy TabbedPanel, you can reference the ids using app.root.ids.id-name or self.ids.id-name e.g. app.root.ids.label3.text or self.ids.label3.text because when your kv file is parsed, kivy collects all the widgets tagged with id’s and places them in this self.ids dictionary type property.

    Example

    main.py

    from kivy.app import App
    from kivy.uix.tabbedpanel import TabbedPanel
    from kivy.lang import Builder
    from kivy.uix.label import Label
    from kivy.uix.button import Button
    
    Builder.load_string("""
    
    <Test>:
        size_hint: .5, .5
        pos_hint: {'center_x': .5, 'center_y': .5}
        do_default_tab: False
    
        TabbedPanelItem:
            text: 'first tab'
            Label:
                text: 'First tab content area'
    
        TabbedPanelItem:
            id: tab2
            text: 'tab2'
    
            BoxLayout:
                id: box1
                orientation: 'vertical'
    
                Label:
                    id: label1
                    text: 'Second tab content area'
                Button:
                    id: button1
                    text: 'Button that does nothing'
    
                BoxLayout:
                    id: box2
                    orientation: 'vertical'
    
                    Label:
                        id: label2
                        text: 'Label 2'
    
                    BoxLayout:
                        id: box3
                        orientation: 'vertical'
    
                        Button:
                            id: button2
                            text: 'Button 2'
                        Label:
                            id: label3
                            text: 'Label 3'
    
        TabbedPanelItem:
            text: 'tab3'
            RstDocument:
                text:
                    '\\n'.join(("Hello world", "-----------",
                    "You are in the third tab."))
    
    """)
    
    
    class Test(TabbedPanel):
    
        def __init__(self, **kwargs):
            super(Test, self).__init__(**kwargs)
            print(f"\nself.ids.items():")
            for key, val in self.ids.items():
                if isinstance(val, Label) or isinstance(val, Button):
                    print(f"\tkey={key}, val={val}, val.text={val.text}")
                else:
                    print(f"\n\tkey={key}, val={val}")
    
            print(f"\nself.ids.label3.text={self.ids.label3.text}")
    
    
    class TabbedPanelApp(App):
        def build(self):
            return Test()
    
    
    if __name__ == '__main__':
        TabbedPanelApp().run()
    

    Output

    Result