Welcome, guest | Sign In | My Account | Store | Cart

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.

Python, 60 lines
 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.

4 comments

Paul Moore 16 years, 6 months ago  # | flag

You need a statement

from __future__ import with_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).

Ronald Longo (author) 16 years, 6 months ago  # | flag

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.

François Petitjean 16 years, 1 month ago  # | flag

do not forget to free the image. I would replace

      self._image             = Tix.PhotoImage( file=image )

by:<pre>
      self._image             = Tix.PhotoImage(master=self._root, file=image )


and add to the __exit__() method<pre>
        del self._image

just after or before<pre>
      self._splash.destroy( )


The spashscreen image may be the biggest static resource of the application and can consume memory in Tk until the root window is destroyed.

</pre></pre></pre>

Gabriel Genellina 14 years, 5 months ago  # | flag

See also recipe 576936

Created by Ronald Longo on Fri, 19 Oct 2007 (PSF)
Python recipes (4591)
Ronald Longo's recipes (2)

Required Modules

Other Information and Tasks