This class provides a very simple and clean way to produce a spash screen for any Tkinter application. It requires Python 2.5 or later.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
from __future__ import with_statement # <-- Python 2.5 ONLY import Tix import time class SplashScreen( object ): def __init__( self, tkRoot, imageFilename, minSplashTime=0 ): self._root = tkRoot self._image = Tix.PhotoImage( file=image ) self._splash = None self._minSplashTime = time.time() + minSplashTime def __enter__( self ): # Remove the app window from the display self._root.withdraw( ) # Calculate the geometry to center the splash image scrnWt = self._root.winfo_screenwidth( ) scrnHt = self._root.winfo_screenheight( ) imgWt = self._image.width() imgHt = self._image.height() imgXPos = (scrnWt / 2) - (imgWt / 2) imgYPos = (scrnHt / 2) - (imgHt / 2) # Create the splash screen self._splash = Tix.Toplevel() self._splash.overrideredirect(1) self._splash.geometry( '+%d+%d' % (imgXPos, imgYPos) ) Tix.Label( self._splash, image=self._image, cursor='watch' ).pack( ) # Force Tk to draw the splash screen outside of mainloop() self._splash.update( ) def __exit__( self, exc_type, exc_value, traceback ): # Make sure the minimum splash time has elapsed timeNow = time.time() if timeNow < self._minSplashTime: time.sleep( self._minSplashTime - timeNow ) # Destroy the splash window self._splash.destroy( ) # Display the application window self._root.deiconify( ) #-------------------------------------------- # Now putting up splash screens is simple # Create the tkRoot window tkRoot = Tix.Tk( ) with SplashScreen( tkRoot, 'splashImage.jpg', 3.0 ): initializeMyApplication( ) buildTheGUI( tkRoot ) tkRoot.mainloop( )
I've struggled for a long time to design a splash screen solution that is both elegant and flexible. Before I knew it was possible to call update() outside of mainloop() to get widgets to display, I would setup a timer callback using after(). It was a very ugly solution. The use of update() and the introduction of the with statement made it possible to encapsulate a splash screen into an object which results in very clean code.
The best way to use this code is to insert the SplashScreen class definition into a module and import it into your application. Generally you want the splash screen up while you initialize you application. Therefore, ideally you will follow the usage that I outline above. That is, create the tk root window, then immedicately start a with statement creating the splash screen. The suite of statements in the body of the with statement can then do all your initialization and build your GUI. When the with statement exits the splash screen is destroyed and your next line of code is to enter the mainloop().
The third parameter to the SplashScreen constructor is optional. It's a minimal time in seconds to display the splash image.
In my example above I actually import Tix rather than Tkinter. This is because I use many of the Tix widgets in my own applications. Importing Tix gives me all the Tix widgets plus everything that I would have gotten if I had imported Tkinter explicitly.
You need a statement
to enable the with syntax in Python 2.5. Also, for Windows users the standard Python 2.5 Windows distribution from python.org doesn't include Tix (I think ActiveState does, but I don't know how/if it's possible to add it into the standard dist, as it's the TCL part that's missing, not the Python code).
Thanks, sorry about missing the import with_statement.
However, Tix has always been included in all the standard Python distributions that I've downloaded (though it's not usually mentioned anywhere). To check, type 'import Tix' at a python interactive prompt. If you get an exception, it's probably not installed. Tix (and for that matter all of tkinter) was not included in Python 2.4, however, that was an oversight by the person who manages the Python installer.
do not forget to free the image. I would replace
See also recipe 576936