Example 15-6 implements a handful of utility pop-up windows in a module, in case they ever prove useful in other programs. Note that the same windows utility module is imported here, to give a common look-and-feel to the popups (icons, titles, and so on).
Example 15-6.PP3E\Internet\Email\PyMailGui\popuputil.py
################################################################ # utility windows - may be useful in other programs ###############################################################
from Tkinter import * from PP3E.Gui.Tools.windows import PopupWindow
class HelpPopup(PopupWindow): """ custom Toplevel that shows help text as scrolled text source button runs a passed-in callback handler alternative: use HTML file and webbrowser module """ myfont = 'system' # customizable
def __init__(self, appname, helptext, iconfile=None, showsource=lambda:0): PopupWindow.__init__(self, appname, 'Help', iconfile) from ScrolledText import ScrolledText # a nonmodal dialog bar = Frame(self) # pack first=clip last bar.pack(side=BOTTOM, fill=X) code = Button(bar, bg='beige', text="Source", command=showsource) quit = Button(bar, bg='beige', text="Cancel", command=self.destroy) code.pack(pady=1, side=LEFT) quit.pack(pady=1, side=LEFT) text = ScrolledText(self) # add Text + scrollbar text.config(font=self.myfont, width=70) # too big for showinfo text.config(bg='steelblue', fg='white') # erase on btn or return text.insert('0.0', helptext) text.pack(expand=YES, fill=BOTH) self.bind("<Return>", (lambda event: self.destroy()))
def askPasswordWindow(appname, prompt): """ modal dialog to input password string getpass.getpass uses stdin, not GUI tkSimpleDialog.askstring echos input """ win = PopupWindow(appname, 'Prompt') # a configured Toplevel Label(win, text=prompt).pack(side=LEFT) entvar = StringVar(win) ent = Entry(win, textvariable=entvar, show='*') # display * for input ent.pack(side=RIGHT, expand=YES, fill=X) ent.bind('<Return>', lambda event: win.destroy()) ent.focus_set(); win.grab_set(); win.wait_window() win.update() # update forces redraw return entvar.get() # ent widget is now gone
class BusyBoxWait(PopupWindow): """ pop up blocking wait message box: thread waits main GUI event thread stays alive during wait but GUI is inoperable during this wait state; uses quit redef here because lower, not leftmost; """ def __init__(self, appname, message): PopupWindow.__init__(self, appname, 'Busy') self.protocol('WM_DELETE_WINDOW', lambda:0) # ignore deletes label = Label(self, text=message + '...') # win.quit() to erase label.config(height=10, width=40, cursor='watch') # busy cursor label.pack() self.makeModal() self.message, self.label = message, label def makeModal(self): self.focus_set() # grab application self.grab_set() # wait for threadexit def changeText(self, newtext): self.label.config(text=self.message + ': ' + newtext) def quit(self): self.destroy() # don't verify quit
class BusyBoxNowait(BusyBoxWait): """ pop up nonblocking wait window call changeText to show progress, quit to close """ def makeModal(self): pass
if __name__ == '__main__': HelpPopup('spam', 'See figure 1...\n') print askPasswordWindow('spam', 'enter password') raw_input('Enter to exit')