Динамическое управление TabbedPanel в Кивах
Я пытаюсь сделать TabbedPannel невидимым в начале,
Затем, когда определенное задание выполнено, я хочу показать вкладки после этого.
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.lang import Builder
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:
text: 'tab2'
BoxLayout:
Label:
text: 'Second tab content area'
Button:
text: 'Button that does nothing'
TabbedPanelItem:
text: 'tab3'
RstDocument:
text:
'\\n'.join(("Hello world", "-----------",
"You are in the third tab."))
""")
class Test(TabbedPanel):
pass
class TabbedPanelApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TabbedPanelApp().run()
Код выше взят из Kivy Document.
То, что я пытаюсь сделать, это
- Скрыть вкладки (также предотвращает перемещение вкладок)
- Когда определенное действие выполнено, вкладки сдвигаются вниз за пределы экрана.
Любая идея?
1 ответ
Звучало как забавное маленькое испытание, поэтому вот что я придумал:
'''
TabbedPanel
============
Test of the widget TabbedPanel.
'''
from kivy.animation import Animation
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelStrip
from kivy.lang import Builder
class Test(TabbedPanel):
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
self.initialTabHeight = None
self.myTabsList = None
self.start_top = None
self.tabs_showing = True
# this TabbedPanelStrip will be a copy of the real one (self._tab_strip)
self.tmp_tab_strip = TabbedPanelStrip(
tabbed_panel=self,
rows=1, size_hint=(None, None),
height=self.tab_height, width=self.tab_width)
# this is the movable Widget that contains the tabs
self.movable_tab_strip = ScrollView(size_hint=(None, None), height=self.tab_height)
# These value are needed to set the width of self.movable_tab_strip, but
# they aren't always available when self.first is called below
self._tab_strip.bind(width=self.tab_strip_width_changed)
self.bind(width=self.panel_width_changed)
Clock.schedule_once(self.first)
def tab_strip_width_changed(self, instance, new_width):
self.movable_tab_strip.width = min(self.tmp_tab_strip.width, self.width)
def panel_width_changed(self, instance, new_width):
self.movable_tab_strip.width = min(self.tmp_tab_strip.width, self.width)
def first(self, *args):
# show tab2, so that the Button will be available
self.switch_to(self.parent.ids.tab2)
# save some info
self.initialTabHeight = self.tab_height
self.myTabsList = self.tab_list.copy()
tsw = 0
for tab in self.myTabsList:
if tab.size_hint_x:
tsw += 100
else:
tsw += tab.width
self.tmp_tab_strip.width = tsw
self.movable_tab_strip.add_widget(self.tmp_tab_strip)
# actually remove the tabs
self.do_clear_widgets()
def do_clear_widgets(self, *args):
# eliminate the tabs and populate the moveable_tab_strip
#self.movable_tab_strip.width = min(self.tmp_tab_strip.width, self.width)
self.tab_height = 0
self.clear_tabs()
for tab in reversed(self.myTabsList):
self.tmp_tab_strip.add_widget(tab)
self.tabs_showing = False
def do_progress(self, animation, widget, progression):
# grow the tab height when the moveable_tab_strip impinges on the TabbedPanel
# this has the effect of appearing to shrink the TappedPanel to the size it will have when the tabs are replaced
if self.start_top > self.movable_tab_strip.y:
self.tab_height = self.start_top - self.movable_tab_strip.y
def do_replace_tabs(self, *args):
# replace the moveable_tab_trip with the actual tabs
self.tmp_tab_strip.clear_widgets()
for tab in reversed(self.myTabsList):
self.add_widget(tab)
self.tab_height = self.initialTabHeight
self.parent.remove_widget(self.movable_tab_strip)
def do_tab_toggle(self, *args):
if self.tabs_showing:
self.do_clear_widgets()
else:
self.anim = Animation(pos=(self.x+2, self.y + self.height - self.movable_tab_strip.height))
self.movable_tab_strip.pos = (self.x + 2, App.get_running_app().root_window.height)
self.start_top = self.top
self.parent.add_widget(self.movable_tab_strip)
self.anim.bind(on_progress=self.do_progress)
self.anim.bind(on_complete=self.do_replace_tabs)
self.anim.start(self.movable_tab_strip)
self.tabs_showing = True
class MyLayout(FloatLayout):
pass
theRoot = Builder.load_string("""
MyLayout:
Test:
id: thePanel
size_hint: .5, .5
pos_hint: {'center_x': .5, 'center_y': .5}
do_default_tab: False
TabbedPanelItem:
text: 'first tab'
Label:
id: theLabel
text: 'First tab content area'
TabbedPanelItem:
id: tab2
text: 'tab2'
BoxLayout:
Label:
text: 'Second tab content area'
Button:
text: 'Button that does something'
on_press: thePanel.do_tab_toggle()
TabbedPanelItem:
id: tab3
text: 'tab3'
RstDocument:
text:
'\\n'.join(("Hello world", "-----------",
"You are in the third tab."))
TabbedPanelItem:
text: 'tab4'
Label:
text: 'This is Tab4'
TabbedPanelItem:
id:tab5
text: 'tab5'
Label:
text: 'This is Tab5'
""")
class TabbedPanelApp(App):
def build(self):
return theRoot
if __name__ == '__main__':
TabbedPanelApp().run()
Идея состоит в том, чтобы создать "подвижную" полосу вкладок, заполнить ее фактическими вкладками из TabbedPanel
, а затем оживить эту полосу вкладок. Я изменил строку языка kv, чтобы поместить все это в FloatLayout
(Я думаю, что это делает Animation
Полегче). Button
, который раньше ничего не делал, теперь переключает вкладки. в do_tab_toggle()
Метод, я устанавливаю положение х подвижной вкладки в положение х TabbedPanel
плюс 2. 2 - фактор выдумки, и я не смог определить, зачем он нужен, и он может отличаться для других TabbedPanel
экземпляров. "Удалить" часть do_tab_toggle()
также может быть анимирован, но это оставлено в качестве упражнения для читателя:-)
Другие варианты - просто очистить вкладки, используя clear_tabs()
метод или для анимации tab_height
собственность TabbedPanel
(анимация высоты до нуля, чтобы скрыть вкладки).
РЕДАКТИРОВАТЬ: добавлена пара привязок для захвата данных, которые не являются надежно доступными, когда first
метод называется.