mirror of https://github.com/kivy/kivy.git
simplify tabbed_pannel_advanced example
This commit is contained in:
parent
33576a90f2
commit
289113a843
|
@ -9,11 +9,20 @@ 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.uix.togglebutton import ToggleButton
|
||||
from kivy.uix.button import Button
|
||||
from kivy.uix.label import Label
|
||||
from kivy.uix.scatter import Scatter
|
||||
from functools import partial
|
||||
from kivy.factory import Factory
|
||||
|
||||
class StandingHeader(TabbedPanelHeader):
|
||||
pass
|
||||
|
||||
class ClosableHeader(TabbedPanelHeader):
|
||||
pass
|
||||
|
||||
class ImageHeader(TabbedPanelHeader):
|
||||
pass
|
||||
|
||||
Factory.register('StandingHeader', cls = StandingHeader)
|
||||
Factory.register('ClosableHeader', cls = ClosableHeader)
|
||||
Factory.register('ImageHeader', cls = ImageHeader)
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
|
@ -25,35 +34,121 @@ Builder.load_string('''
|
|||
text: 'Press to show Tabbed Panel'
|
||||
on_release: root.show_tab()
|
||||
|
||||
<PanelTest>
|
||||
size_hint: (.54, .45)
|
||||
pos_hint: {'center_x': .5, 'y': .55}
|
||||
<StandingHeader>
|
||||
color: 0,0,0,0
|
||||
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: root.center
|
||||
#pos: root.x - root.width/2, root.y
|
||||
Label:
|
||||
id: lbl
|
||||
text: root.text
|
||||
size: root.size
|
||||
pos: 0,0
|
||||
|
||||
<PanelLeft>
|
||||
size_hint: (.45, .45)
|
||||
pos_hint: {'center_x': .25, 'y': .55}
|
||||
#replace the default tab with our custom tab
|
||||
default_tab: def_tab
|
||||
tab_width: 40
|
||||
tab_height: 70
|
||||
FloatLayout:
|
||||
RstDocument:
|
||||
id: default_content
|
||||
text: 'Standing tabs\\n-------------\\n'
|
||||
Image:
|
||||
id: tab_2_content
|
||||
pos:self.parent.pos
|
||||
size: self.parent.size
|
||||
source: 'data/images/defaulttheme-0.png'
|
||||
Image:
|
||||
id: tab_3_content
|
||||
pos:self.parent.pos
|
||||
size: self.parent.size
|
||||
source: 'data/images/image-loading.gif'
|
||||
StandingHeader:
|
||||
id: def_tab
|
||||
content: default_content
|
||||
text: 'Default tab'
|
||||
StandingHeader:
|
||||
content: tab_2_content
|
||||
text: 'tab 2'
|
||||
StandingHeader:
|
||||
content: tab_3_content
|
||||
text: 'tab 3'
|
||||
|
||||
<ClosableHeader>
|
||||
color: 0,0,0,0
|
||||
BoxLayout:
|
||||
pos: root.pos
|
||||
size_hint: None, None
|
||||
size: root.size
|
||||
Label:
|
||||
id: lbl
|
||||
text: root.text
|
||||
BoxLayout:
|
||||
size_hint: None, 1
|
||||
width: 18
|
||||
orientation: 'vertical'
|
||||
Widget:
|
||||
Button:
|
||||
border: 0,0,0,0
|
||||
background_normal: 'tools/theming/defaulttheme/close.png'
|
||||
on_release: root.panel.remove_widget(root)
|
||||
Widget:
|
||||
|
||||
|
||||
<PanelRight>
|
||||
tab_pos: 'top_right'
|
||||
size_hint: (.45, .45)
|
||||
pos_hint: {'center_x': .75, 'y': .55}
|
||||
default_tab: def_tab
|
||||
FloatLayout:
|
||||
RstDocument:
|
||||
id: default_content
|
||||
text: 'Closable tabs\\n-------------\\n'
|
||||
Image:
|
||||
id: tab_2_content
|
||||
pos:self.parent.pos
|
||||
size: self.parent.size
|
||||
source: 'data/images/defaulttheme-0.png'
|
||||
Image:
|
||||
id: tab_3_content
|
||||
pos:self.parent.pos
|
||||
size: self.parent.size
|
||||
source: 'data/images/image-loading.gif'
|
||||
ClosableHeader:
|
||||
id: def_tab
|
||||
text: 'default\\ntab'
|
||||
content:default_content
|
||||
panel: root
|
||||
ClosableHeader:
|
||||
text: 'tab2'
|
||||
content: tab_2_content
|
||||
panel: root
|
||||
ClosableHeader:
|
||||
text: 'tab3'
|
||||
content: tab_3_content
|
||||
panel: root
|
||||
|
||||
<PanelbLeft>
|
||||
tab_pos: 'bottom_left'
|
||||
size_hint: (.45, .45)
|
||||
pos_hint: {'center_x': .25, 'y': .02}
|
||||
default_tab_text: 'Settings'
|
||||
default_tab_content: default_content
|
||||
FloatLayout:
|
||||
BoxLayout
|
||||
RstDocument:
|
||||
id: default_content
|
||||
pos:self.parent.pos
|
||||
size: self.parent.size
|
||||
Label:
|
||||
text: 'everything is relative!'
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
BubbleButton:
|
||||
text:'press to add\\n a tab head'
|
||||
on_release: root.add_heading()
|
||||
ToggleButton:
|
||||
group: 'tab_style'
|
||||
text: ' Economic\\n Long Tabs'
|
||||
on_state: root.economize_tabs(self)
|
||||
ToggleButton:
|
||||
group: 'tab_style'
|
||||
text: 'Image tabs'
|
||||
on_state: root.image_tabs(self)
|
||||
ToggleButton:
|
||||
group: 'tab_style'
|
||||
text: 'Closable tabs'
|
||||
on_state: root.closable_tabs(self)
|
||||
text: 'Normal tabs\\n-------------\\n press ' +\
|
||||
'background button to change tab_pos'
|
||||
Image:
|
||||
id: tab_2_content
|
||||
pos:self.parent.pos
|
||||
|
@ -70,6 +165,38 @@ Builder.load_string('''
|
|||
TabbedPanelHeader:
|
||||
text: 'tab3'
|
||||
content: tab_3_content
|
||||
|
||||
<ImageHeader>
|
||||
border: 0, 0, 0, 0
|
||||
background_down: 'softboy.png'
|
||||
background_normal:'sequenced_images/data/images/info.png'
|
||||
|
||||
<PanelbRight>
|
||||
tab_pos: 'right_top'
|
||||
size_hint: (.45, .45)
|
||||
pos_hint: {'center_x': .75, 'y': .02}
|
||||
default_tab: def_tab
|
||||
FloatLayout:
|
||||
RstDocument:
|
||||
id: default_content
|
||||
text: 'Image tabs\\n-------------\\n'
|
||||
Image:
|
||||
id: tab_2_content
|
||||
pos:self.parent.pos
|
||||
size: self.parent.size
|
||||
source: 'data/images/defaulttheme-0.png'
|
||||
Image:
|
||||
id: tab_3_content
|
||||
pos:self.parent.pos
|
||||
size: self.parent.size
|
||||
source: 'data/images/image-loading.gif'
|
||||
ImageHeader:
|
||||
id: def_tab
|
||||
content:default_content
|
||||
ImageHeader:
|
||||
content: tab_2_content
|
||||
ImageHeader:
|
||||
content: tab_3_content
|
||||
''')
|
||||
|
||||
|
||||
|
@ -100,118 +227,29 @@ class Tp(TabbedPanel):
|
|||
else:
|
||||
_on_complete()
|
||||
|
||||
class PanelLeft(Tp):
|
||||
pass
|
||||
|
||||
class PanelTest(Tp):
|
||||
class PanelRight(Tp):
|
||||
pass
|
||||
|
||||
def update_pos(self, sctr, tab, *l):
|
||||
sctr.pos = tab.pos
|
||||
|
||||
def update_sctr_rotation(self, sctr, *l):
|
||||
sctr.rotation = 90 if self.tab_pos[0] != 'l' else -90
|
||||
|
||||
def economize_tabs(self, *l):
|
||||
# switch width and height for long tabs
|
||||
self.tab_width, self.tab_height = self.tab_height, self.tab_width
|
||||
|
||||
but_state = l[0].state
|
||||
for tab in self.tab_list:
|
||||
if but_state == 'normal':
|
||||
try:
|
||||
tab.color = tab.old_color
|
||||
except AttributeError:
|
||||
pass
|
||||
# remove scatter and label
|
||||
tab.clear_widgets()
|
||||
else:
|
||||
# add a scatter with a label rotated to display standing text
|
||||
lbl = Label(text = tab.text,
|
||||
size_hint=(None, None), size=tab.size)
|
||||
sctr = Scatter(do_translation = False,
|
||||
rotation = 90 if self.tab_pos[0] != 'l' else -90,
|
||||
do_rotation = False,
|
||||
do_scale = False,
|
||||
size_hint = (None, None),
|
||||
auto_bring_to_front = False,
|
||||
size = lbl.size)
|
||||
tab.add_widget(sctr)
|
||||
sctr.add_widget(lbl)
|
||||
# update scatter rotation on tab_pos required only if you need
|
||||
# to dynamically change the tab_pos when in long tabs mode and
|
||||
# going from 'bottom_right' to 'left_*' tab_pos
|
||||
self.bind(tab_pos = partial(self.update_sctr_rotation, sctr))
|
||||
tab.old_color = tab.color
|
||||
tab.color = (0, 0, 0, 0)
|
||||
|
||||
tab.bind(pos = partial(self.update_pos, sctr, tab))
|
||||
|
||||
def position_close_btn(self, tab, btn, *l):
|
||||
btn.pos = (tab.right - btn.width, tab.top - btn.height)
|
||||
|
||||
def close_tab(self, tab, *l):
|
||||
self.remove_widget(tab)
|
||||
|
||||
def closable_tabs(self, *l):
|
||||
but_state = l[0].state
|
||||
for tab in self.tab_list:
|
||||
if but_state == 'normal':
|
||||
tab.clear_widgets()
|
||||
else:
|
||||
btn = Button(background_normal =
|
||||
'tools/theming/defaulttheme/close.png',
|
||||
size_hint = (None, None),
|
||||
size = (15, 15),
|
||||
border = (0, 0, 0, 0))
|
||||
tab.add_widget(btn)
|
||||
btn.bind(on_release = partial(self.close_tab, tab))
|
||||
btn.pos = (tab.right - btn.width, tab.top - btn.height)
|
||||
tab.bind(pos = partial(self.position_close_btn, tab, btn))
|
||||
|
||||
def image_tabs(self, but):
|
||||
but_state = but.state
|
||||
if but_state == 'normal':
|
||||
self.tab_height = self.old_height
|
||||
for tab in self.tab_list:
|
||||
try:
|
||||
tab.color = tab.old_color
|
||||
tab.background_down = tab.old_img
|
||||
tab.background_normal = tab.old_img_normal
|
||||
except AttributeError:
|
||||
pass
|
||||
# all new tabs should also follow style
|
||||
Builder.load_string(str('''
|
||||
<TabbedPanelHeader>:
|
||||
background_normal: '%s'
|
||||
background_down: '%s'
|
||||
color: (%x, %x, %x, %x)
|
||||
font_size: 11''') %(tab.old_img_normal, tab.old_img,
|
||||
tab.color[0], tab.color[1], tab.color[2], tab.color[3]))
|
||||
else:
|
||||
self.old_height = self.tab_height
|
||||
self.tab_height = 50
|
||||
for tab in self.tab_list:
|
||||
tab.old_img = tab.background_down
|
||||
tab.background_down = 'softboy.png'
|
||||
tab.old_img_normal = tab.background_normal
|
||||
tab.background_normal = 'sequenced_images/data/images/info.png'
|
||||
tab.old_color = tab.color
|
||||
tab.color = (0, 0, 0, 0)
|
||||
# all new tabs should also follow style
|
||||
Builder.load_string('''
|
||||
<TabbedPanelHeader>:
|
||||
background_normal: 'sequenced_images/data/images/info.png'
|
||||
background_down: 'softboy.png'
|
||||
color: 0,0,0,0
|
||||
font_size: 11''')
|
||||
|
||||
def add_heading(self):
|
||||
self.add_widget(TabbedPanelHeader(text = 'tabx'))
|
||||
class PanelbLeft(Tp):
|
||||
pass
|
||||
|
||||
class PanelbRight(Tp):
|
||||
pass
|
||||
|
||||
class TabShowcase(FloatLayout):
|
||||
|
||||
def show_tab(self):
|
||||
if not hasattr(self, 'tab'):
|
||||
self.tab = tab = PanelTest()
|
||||
self.tab = tab = PanelLeft()
|
||||
self.add_widget(tab)
|
||||
self.tab = tab = PanelRight()
|
||||
self.add_widget(tab)
|
||||
self.tab = tab = PanelbRight()
|
||||
self.add_widget(tab)
|
||||
self.tab = tab = PanelbLeft()
|
||||
self.add_widget(tab)
|
||||
else:
|
||||
values = ('left_top', 'left_mid', 'left_bottom', 'top_left',
|
||||
|
|
|
@ -14,8 +14,7 @@ TabbedPanel
|
|||
|
||||
The `TabbedPanel` widget is exactly what it sounds like, a Tabbed Panel.
|
||||
|
||||
The :class:`TabbedPanel` contains one tabbed panel by default pointing towards
|
||||
the direction you choose.
|
||||
The :class:`TabbedPanel` contains one tab by default.
|
||||
|
||||
Simple example
|
||||
--------------
|
||||
|
@ -249,6 +248,22 @@ class TabbedPanel(GridLayout):
|
|||
default to 'None'.
|
||||
'''
|
||||
|
||||
def get_def_tab(self):
|
||||
return self._default_tab
|
||||
|
||||
def set_def_tab(self, *l):
|
||||
old_tab = self._default_tab
|
||||
self._default_tab = l[0]
|
||||
self.remove_widget(old_tab)
|
||||
self.switch_to(l[0])
|
||||
l[0].state = 'down'
|
||||
|
||||
default_tab = AliasProperty(get_def_tab, set_def_tab)
|
||||
'''Holds the default_tab
|
||||
|
||||
:data:`default_tab` is a :class:`~kivy.properties.AliasProperty`
|
||||
'''
|
||||
|
||||
def get_def_tab_content(self):
|
||||
return self.default_tab.content
|
||||
|
||||
|
@ -279,13 +294,12 @@ class TabbedPanel(GridLayout):
|
|||
self._tab_strip = _tabs = TabbedPanelStrip(tabbed_panel = self,
|
||||
rows = 1, cols = 99, size_hint = (None, None),\
|
||||
height = self.tab_height, width = self.tab_width)
|
||||
self.default_tab = default_tab = \
|
||||
self._default_tab = default_tab = \
|
||||
TabbedPanelHeader(text = self.default_tab_text,
|
||||
height = self.tab_height, state = 'down',
|
||||
width = self.tab_width)
|
||||
_tabs.add_widget(default_tab)
|
||||
default_tab.group = '__tab%r__' %_tabs.uid
|
||||
default_tab.bind(on_release=self.on_default_tab)
|
||||
self._partial_update_scrollview = None
|
||||
|
||||
self.content = content = TabbedPanelContent()
|
||||
|
@ -293,14 +307,10 @@ class TabbedPanel(GridLayout):
|
|||
self.add_widget(content)
|
||||
self.on_tab_pos()
|
||||
#make default tab the active tab
|
||||
self.switch_to(self.default_tab)
|
||||
|
||||
def on_default_tab(self, *l):
|
||||
'''This event is fired when the default tab is selected.
|
||||
'''
|
||||
self.switch_to(self._default_tab)
|
||||
|
||||
def on_default_tab_text(self, *l):
|
||||
self.default_tab.text = self.default_tab_text
|
||||
self._default_tab.text = self.default_tab_text
|
||||
|
||||
def switch_to(self, header):
|
||||
'''Switch to a specific panel header
|
||||
|
@ -333,11 +343,11 @@ class TabbedPanel(GridLayout):
|
|||
if l[0] == content or l[0] == self._tab_layout:
|
||||
super(TabbedPanel, self).remove_widget(*l)
|
||||
elif isinstance(l[0], TabbedPanelHeader):
|
||||
if l[0]!= self.default_tab:
|
||||
if l[0]!= self._default_tab:
|
||||
self_tabs = self._tab_strip
|
||||
self_tabs.remove_widget(l[0])
|
||||
if l[0].state == 'down':
|
||||
self.default_tab.on_release()
|
||||
self._default_tab.on_release()
|
||||
self_tabs.width -= l[0].width
|
||||
self.reposition_tabs()
|
||||
else:
|
||||
|
@ -358,7 +368,7 @@ class TabbedPanel(GridLayout):
|
|||
def clear_tabs(self, *l):
|
||||
self_tabs = self._tab_strip
|
||||
self_tabs.clear_widgets()
|
||||
self_default_tab = self.default_tab
|
||||
self_default_tab = self._default_tab
|
||||
self_tabs.add_widget(self_default_tab)
|
||||
self_tabs.width = self_default_tab.width
|
||||
self.reposition_tabs()
|
||||
|
|
Loading…
Reference in New Issue