Credit: Brent Burley
You need to embed GIF images inside your source code—for use in Tkinter buttons, labels, etc.—to make toolbars and the like without worrying about installing the right icon files.
A lively Tkinter GUI can include many small images. However, you
probably shouldn’t require that a small GIF file be
present for each of these; ensuring the presence of many small files
is a bother, and if they’re missing, your GUI may be
unusable or look wrong. Fortunately, you can construct
Tkinter
PhotoImage
objects with inline data.
It’s easy to convert a GIF to inline form as Python
source code:
import base64 print "icon='''\ " + base64.encodestring(open("icon.gif", "rb").read( )) + "'''"
You can then split the result into lines of reasonable length:
icon='''R0lGODdhFQAVAPMAAAQ2PESapISCBASCBMTCxPxmNCQiJJya/ISChGRmzPz+/PxmzDQyZ DQyZDQyZDQyZCwAAAAAFQAVAAAElJDISau9Vh2WMD0gqHHelJwnsXVloqDd2hrMm8pYYiSHYfMMRm 53ULlQHGFFx1MZCciUiVOsPmEkKNVp3UBhJ4Ohy1UxerSgJGZMMBbcBACQlVhRiHvaUsXHgywTdyc LdxyB gm1vcTyIZW4MeU6NgQEBXEGRcQcIlwQIAwEHoioCAgWmCZ0Iq5+hA6wIpqislgGhthEAOw== '''
and use it in Tkinter:
import Tkinter
root = Tkinter.Tk( )
iconImage = Tkinter.PhotoImage(master=root, data=icon)
Tkinter.Button(image=iconImage).pack( )
The basic technique is to encode the GIF with the standard Python
module base64
and store the results as a string
literal in the Python code, which will be passed to
Tkinter’s PhotoImage
. The current
release of PhotoImage
supports GIF and PPM, but
inline data is supported only for GIF. You can use
file='filename'
, instead of
data=string
, for either GIF or PPM.
You must keep a reference to the PhotoImage
object
yourself; it is not kept by the Tkinter widget. If you pass it to
Button
and forget it, you will become very
frustrated! Here’s an easy workaround for this minor
annoyance:
def makeImageWidget(icondata, *args, **kwds): if args: klass = args.pop(0) else: klass = Tkinter.Button class Widget(klass): def _ _init_ _(self, image, *args, **kwds): kwds['image']=image klass._ _init_ _(self, args, kwds) self._ _image = image return Widget(Tkinter.PhotoImage(data=icondata), *args, **kwds)
Using this, the equivalent of the example in the recipe becomes:
makeImageWidget(icon).pack( )
The master
argument on
PhotoImage
is optional; it defaults to the default application window. If you
create a new application window (by calling Tk
again), you will need to create your images in that context and
supply the master argument, so the
makeImageWidget
function would need to be updated to let you optionally pass the
master argument to the PhotoImage
constructor.
However, most applications do not require this.
Information about Tkinter can be obtained from a variety of sources, such as Pythonware’s An Introduction to Tkinter, by Fredrik Lundh (http://www.pythonware.com/library), New Mexico Tech’s Tkinter reference (http://www.nmt.edu/tcc/help/lang/python/docs.html), and various books.