''' TabbedPanel ============ Test of the widget TabbedPanel showing all capabilities. ''' from kivy.app import App from kivy.animation import Animation from kivy.uix.floatlayout import FloatLayout from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader from kivy.factory import Factory class StandingHeader(TabbedPanelHeader): pass class CloseableHeader(TabbedPanelHeader): pass Factory.register('StandingHeader', cls=StandingHeader) Factory.register('CloseableHeader', cls=CloseableHeader) from kivy.lang import Builder Builder.load_string(''' but: _but Button: id: _but text: 'Press to show Tabbed Panel' on_release: root.show_tab() color: 0,0,0,0 disabled_color: self.color Scatter: do_translation: False do_scale: False do_rotation: False auto_bring_to_front: False rotation: 70 size_hint: None, None size: lbl.size center_x: root.center_x center_y: root.center_y Label: id: lbl text: root.text size: root.size color: 1, 1, 1, .5 if self.disabled else 1 pos: 0,0 size_hint: (.45, .45) pos_hint: {'center_x': .25, 'y': .55} # replace the default tab with our custom tab class default_tab_cls: sh.__class__ do_default_tab: True default_tab_content: default_content.__self__ tab_width: 40 tab_height: 70 FloatLayout: RstDocument: id: default_content text: '\\n'.join(("Standing tabs", "-------------",\ "Tabs in \\'%s\\' position" %root.tab_pos)) Image: id: tab_2_content source: 'data/images/defaulttheme-0.png' Image: id: tab_3_content source: 'data/images/image-loading.zip' StandingHeader: id: sh content: tab_2_content.__self__ text: 'tab 2' StandingHeader: content: tab_3_content text: 'tab 3' color: 0,0,0,0 disabled_color: self.color # variable tab_width text: 'tabx' size_hint_x: None width: self.texture_size[0] + 40 BoxLayout: pos: root.pos size_hint: None, None size: root.size padding: 3 Label: id: lbl text: root.text BoxLayout: size_hint: None, 1 orientation: 'vertical' width: 22 Image: source: 'tools/theming/defaulttheme/close.png' on_touch_down: if self.collide_point(*args[1].pos) :\ root.panel.remove_widget(root) tab_pos: 'top_right' size_hint: (.45, .45) pos_hint: {'center_x': .75, 'y': .55} # replace the default tab with our custom tab default_tab: def_tab # allow variable tab width tab_width: None FloatLayout: RstDocument: id: default_content text: '\\n'.join(("Closeable tabs", "---------------",\ "- The tabs above are also scrollable",\ "- Tabs in \\'%s\\' position" %root.tab_pos)) Image: id: tab_2_content source: 'data/images/defaulttheme-0.png' BoxLayout: id: tab_3_content BubbleButton: text: 'Press to add new tab' on_release: root.add_header() BubbleButton: text: 'Press set this tab as default' on_release: root.default_tab = tab3 CloseableHeader: id: def_tab text: 'default tab' content:default_content.__self__ panel: root CloseableHeader: text: 'tab2' content: tab_2_content.__self__ panel: root CloseableHeader: id: tab3 text: 'tab3' content: tab_3_content.__self__ panel: root CloseableHeader: panel: root CloseableHeader: panel: root CloseableHeader: panel: root CloseableHeader: panel: root CloseableHeader: panel: root CloseableHeader: panel: root CloseableHeader: panel: root tab_pos: 'bottom_left' size_hint: (.45, .45) pos_hint: {'center_x': .25, 'y': .02} do_default_tab: False TabbedPanelItem: id: settings text: 'Settings' RstDocument: text: '\\n'.join(("Normal tabs", "-------------",\ "Tabs in \\'%s\\' position" %root.tab_pos)) TabbedPanelItem: text: 'tab2' BubbleButton: text: 'switch to settings' on_press: root.switch_to(settings) TabbedPanelItem: text: 'tab3' Image: source: 'data/images/image-loading.zip' tab_pos: 'right_top' size_hint: (.45, .45) pos_hint: {'center_x': .75, 'y': .02} default_tab: def_tab tab_height: img.width FloatLayout: RstDocument: id: default_content text: '\\n'.join(("Image tabs","-------------",\ "1. Normal image tab","2. Image with Text","3. Rotated Image",\ "4. Tabs in \\'%s\\' position" %root.tab_pos)) Image: id: tab_2_content source: 'data/images/defaulttheme-0.png' VideoPlayer: id: tab_3_content source: 'cityCC0.mpg' TabbedPanelHeader: id: def_tab content:default_content.__self__ border: 0, 0, 0, 0 background_down: 'cityCC0.png' background_normal:'sequenced_images/data/images/info.png' TabbedPanelHeader: id: tph content: tab_2_content.__self__ BoxLayout: pos: tph.pos size: tph.size orientation: 'vertical' Image: source: 'sequenced_images/data/images/info.png'\ if tph.state == 'normal' else 'cityCC0.png' Label: text: 'text & img' TabbedPanelHeader: id: my_header content: tab_3_content.__self__ Scatter: do_translation: False do_scale: False do_rotation: False auto_bring_to_front: False rotation: 90 size_hint: None, None size: img.size center: my_header.center Image: id: img source: 'sequenced_images/data/images/info.png'\ if my_header.state == 'normal' else 'cityCC0.png' size: my_header.size fit_mode: "fill" ''') class Tp(TabbedPanel): # override tab switching method to animate on tab switch def switch_to(self, header): anim = Animation(opacity=0, d=.24, t='in_out_quad') def start_anim(_anim, child, in_complete, *lt): _anim.start(child) def _on_complete(*lt): if header.content: header.content.opacity = 0 anim = Animation(opacity=1, d=.43, t='in_out_quad') start_anim(anim, header.content, True) super(Tp, self).switch_to(header) anim.bind(on_complete=_on_complete) if self.current_tab.content: start_anim(anim, self.current_tab.content, False) else: _on_complete() class PanelLeft(Tp): pass class PanelRight(Tp): def add_header(self): self.add_widget(CloseableHeader(panel=self)) class PanelbLeft(Tp): pass class PanelbRight(Tp): pass class TabShowcase(FloatLayout): def show_tab(self): if not hasattr(self, 'tab'): self.tab = tab = PanelLeft() self.add_widget(tab) self.tab1 = tab = PanelRight() self.add_widget(tab) self.tab2 = tab = PanelbRight() self.add_widget(tab) self.tab3 = tab = PanelbLeft() self.add_widget(tab) self.but.text = \ 'Tabs in variable positions, press to change to top_left' else: values = ('left_top', 'left_mid', 'left_bottom', 'top_left', 'top_mid', 'top_right', 'right_top', 'right_mid', 'right_bottom', 'bottom_left', 'bottom_mid', 'bottom_right') index = values.index(self.tab.tab_pos) self.tab.tab_pos = self.tab1.tab_pos = self.tab2.tab_pos\ = self.tab3.tab_pos = values[(index + 1) % len(values)] self.but.text = 'Tabs in \'%s\' position,' % self.tab.tab_pos\ + '\n press to change to next pos' class TestTabApp(App): def build(self): return TabShowcase() if __name__ == '__main__': TestTabApp().run()