Skip to content

Instantly share code, notes, and snippets.

@rnixx
Created June 15, 2015 08:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rnixx/2aab5e13e17c1582b6dd to your computer and use it in GitHub Desktop.
Save rnixx/2aab5e13e17c1582b6dd to your computer and use it in GitHub Desktop.
Kivy: Extended Screen manager with better convenience for switching between screens.
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.screenmanager import ScreenManagerException
from kivy.uix.screenmanager import Screen
class ExtScreenManager(ScreenManager):
def __init__(self, **kwargs):
Logger.debug('ExtScreenManager.__init__')
self.register_event_type('on_finish_screen_switch')
super(ExtScreenManager, self).__init__(**kwargs)
def on_finish_screen_switch(self, *args):
"""Default handler.
"""
Logger.debug('ExtScreenManager.on_finish_screen_switch')
def display_screen(self, screen, **options):
"""Display screen.
Given ``screen`` can be either a screen instance or a screen name as
string.
If screen instance is given and not child of manager yet, it gets added
as long as no screen with same name already exists.
If screen name is given, corresponding screen must already be contained
in manager.
``options`` might contain a :attr:`remove` flag, which causes the
already displayed screen to be removed after switching to given screen.
:attr:`transition` instance can be given in ``options`` to use a
custom transition for this screen switch.
"""
Logger.debug('ExtScreenManager.display_screen')
# screen must be given
assert(screen is not None)
# flag whether to add given screen
add_screen = False
# remember currently displayed screen
current_screen = self.current_screen
# screen instance given
if isinstance(screen, Screen):
# given screen already displayed
if current_screen is screen:
return
screen_name = screen.name
# screen not contained in self
if screen not in self.screens:
# screen with name already contained
if self.has_screen(screen_name):
raise ScreenManagerException(
'Screen with name {0} already exists'.format(
screen_name
)
)
# screen needs to be added
add_screen = True
# no screen instance
else:
# screen name expected
if not isinstance(screen, string_types):
raise ScreenManagerException(
'Given screen must be either Screen instance or screen '
'name as string'
)
screen_name = screen
# no screen with given name in self
if not self.has_screen(screen_name):
raise ScreenManagerException(
'No screen found for given screen name'
)
# given screen already displayed
if current_screen and current_screen.name == screen_name:
return
# option whether to remove previous screen
remove_prev = options.pop("remove", False)
# custom transition to use
custom_transition = options.pop("transition", None)
# remember original transition
orgin_transition = self.transition
# use custom transition if given
if custom_transition:
# update transition options
for key, value in iteritems(options):
setattr(custom_transition, key, value)
# set transition
self.transition = custom_transition
def finish_screen_switch(transition):
# remove previous screen
if remove_prev and current_screen in self.children:
self.remove_widget(current_screen)
# reset transition
if custom_transition:
self.transition = orgin_transition
# unbind callback
transition.unbind(on_complete=finish_screen_switch)
self.dispatch('on_finish_screen_switch')
# bind callback
self.transition.bind(on_complete=finish_screen_switch)
# add screen if necessary
if add_screen:
# initial display
initial = self.current is None
# add screen
self.add_widget(screen)
# current gets set on add_widget if initial display
if not initial:
self.current = screen_name
# set current screen
else:
self.current = screen_name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment