I’ve been working on a Python app consisting of a main.py and a gui.kv. All screens (“Main”, “First”, “Second”) are managed by the ScreenManager as shown in the example main.py. Now I would like to link a tab to each screen. By pressing the corresponding tab the screen shall switch. What I managed so far is the addition of a TabbedPanel with 3 TabbedPanelItems (“Main”, “First”, “Second”) to the gui.kv.
The problem: The TappedPanelItem event (on_release: root.manager.current= 'first') doesn’t work as intended. When I press the tab “First” once, the program switches to a blank screen and the “Main” tab marking is still illuminated. The second time I press the tab “First” the “First” screen finally shows the “First”-Screen and the “First“ tab marking illuminates.
main.py:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.floatlayout import FloatLayout
class TabbedTest(TabbedPanel):
pass
class MainScreen(Screen):
pass
class Firstscreen(Screen):
pass
class Secondscreen(Screen):
pass
class TabTest_with_Screenmanager_V2(App):
def build(self):
root = FloatLayout()
#self.tabbedtest = TabbedTest(size_hint_y=0.5, pos_hint={'top': 1.0})
#root.add_widget(self.tabbedtest)
# Create the screen manager
sm = ScreenManager(size_hint_y=0.99, pos_hint={'y': 0},transition=NoTransition())
sm.add_widget(MainScreen(name='main'))
sm.add_widget(Firstscreen(name='first'))
sm.add_widget(Secondscreen(name='second'))
root.add_widget(sm)
return root
if __name__ == '__main__':
TabTest_with_Screenmanager_V2().run()
TabTest_with_Screenmanager_V2.kv:
<MainScreen>:
id: main
TabbedPanel:
do_default_tab: False
TabbedPanelItem:
text:"Main"
BoxLayout:
Label:
text:'Main'
TabbedPanelItem:
text:"First"
on_release: root.manager.current= 'first'
TabbedPanelItem:
text:"Second"
on_release:root.manager.current= 'second'
<Firstscreen>:
id: first
TabbedPanel:
do_default_tab: False
TabbedPanelItem:
text:"Main"
on_state: if self.state == "down":root.manager.current= 'main'
TabbedPanelItem:
text:"First"
BoxLayout:
Label:
text:"first"
TabbedPanelItem:
text:"Second"
on_state: if self.state == "down":root.manager.current= 'second'
<Secondscreen>:
id: second
TabbedPanel:
do_default_tab: False
TabbedPanelItem:
text:"Main"
on_state: if self.state == "down":root.manager.current= 'main'
TabbedPanelItem:
text:"First"
on_state: if self.state == "down":root.manager.current= 'first'
TabbedPanelItem:
text:"Second"
BoxLayout:
Label:
text:'second'
Objective: When I press a tab the program shall switch to the corresponding screen and illuminate the corresponding tab, immediately. Do you have any idea what kind of event might work or is there better solution?
You can use some ids
and the on_enter()
method of each Screen
to do this.
First, assign an id
to the TabbedPanel
and another to the default tab that you want to be opened when you enter that Screen
. For example:
<MainScreen>:
id: main
TabbedPanel:
id: tab
do_default_tab: False
TabbedPanelItem:
id: home_tab
text:"Main"
BoxLayout:
Label:
text:'Main'
TabbedPanelItem:
text:"First"
on_release: root.manager.current='first'
TabbedPanelItem:
text:"Second"
on_release:root.manager.current= 'second'
Then add an on_enter()
method to that Screen
:
class MainScreen(Screen):
def on_enter(self, *args):
tab = self.ids.tab
home_tab = self.ids.home_tab
Clock.schedule_once(lambda *arges: tab.switch_to(home_tab))
The same scheme of ids
can be added to each Screen
, and the identical on_enter()
method can be added to each Screen
.