imgobj = PhotoImage(file=imgpath)
Label(self, image=imgobj).pack()
print(imgpath, imgobj.width(), imgobj.height()) # size in pixels
self.savephoto = imgobj # keep reference on me
def viewer(imgdir, kind=Toplevel, cols=None):
"""
make thumb links window for an image directory: one thumb button per image;
use kind=Tk to show in main app window, or Frame container (pack); imgfile
differs per loop: must save with a default; photoimage objs must be saved:
erased if reclaimed; packed row frames (versus grids, fixed-sizes, canvas);
"""
win = kind()
win.title('Viewer: ' + imgdir)
quit = Button(win, text='Quit', command=win.quit, bg='beige') # pack first
quit.pack(fill=X, side=BOTTOM) # so clip last
thumbs = makeThumbs(imgdir)
if not cols:
cols = int(math.ceil(math.sqrt(len(thumbs)))) # fixed or N x N
savephotos = []
while thumbs:
thumbsrow, thumbs = thumbs[:cols], thumbs[cols:]
row = Frame(win)
row.pack(fill=BOTH)
for (imgfile, imgobj) in thumbsrow:
photo = PhotoImage(imgobj)
link = Button(row, image=photo)
handler = lambda savefile=imgfile: ViewOne(imgdir, savefile)
link.config(command=handler)
link.pack(side=LEFT, expand=YES)
savephotos.append(photo)
return win, savephotos
if name == 'main':
imgdir = (len(sys.argv) > 1 and sys.argv[1]) or 'images'
main, save = viewer(imgdir, kind=Tk)
main.mainloop()
Notice how this code’s viewer must pass in the imgfile to the generated callback han-
dler with a default argument; because imgfile is a loop variable, all callbacks will have
its final loop iteration value if its current value is not saved this way (all buttons would
open the same image!). Also notice we keep a list of references to the photo image
objects; photos are erased when their object is garbage collected, even if they are cur-
rently being displayed. To avoid this, we generate references in a long-lived list.
Figure 8-45 shows the main thumbnail selection window generated by Example 8-45
when viewing the default images subdirectory in the examples source tree (resized here
for display). As in the previous examples, you can pass in an optional directory name
to run the viewer on a directory of your own (for instance, one copied from your digital
camera). Clicking a thumbnail button in the main window opens a corresponding im-
age in a pop-up window; Figure 8-46 captures one.
498 | Chapter 8: A tkinter Tour, Part 1