File: pymailgui-products/unzipped/PyMailGui-PP4E/popuputil.py
""" ############################################################################# utility windows - may be useful in other programs ############################################################################# """ from tkinter import * from PP4E.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 3.0 alternative: use HTML file and webbrowser module """ myfont = 'system' # customizable mywidth = 78 # 3.0: start width def __init__(self, appname, helptext, iconfile=None, showsource=lambda:0): PopupWindow.__init__(self, appname, 'Help', iconfile) from tkinter.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) text.config(width=self.mywidth) # 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, parent=None): """ modal dialog to input password string getpass.getpass uses stdin, not GUI tkSimpleDialog.askstring echoes input Dec2015: try to ensure window on-top+focus: not in rare cases, but unrelated issues? never used if password file configured; """ 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()) if parent != None: # [4.0] post popup on parent (else very distant on Linux) parentupperleftcorner = (parent.winfo_rootx(), parent.winfo_rooty()) win.geometry('+%d+%d' % parentupperleftcorner) if parent != None and sys.platform.startswith(('linux', 'darwin')): # [4.0] ensure window not covered on Linux and Mac OS X (Windows ok) win.wait_visibility() win.transient(parent) # [4.0] are there too many updates here? win.update() # Dec2015: ensure on top? win.grab_set(); ent.focus_set(); win.wait_window() # Dec2015: try entry 2nd? 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, parent=None): 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() if parent != None: # [4.0] post popup on parent initially (else very distant on Linux) parentupperleftcorner = (parent.winfo_rootx(), parent.winfo_rooty()) self.geometry('+%d+%d' % parentupperleftcorner) self.message, self.label = message, label self.makeModal(parent) def makeModal(self, parent): if parent != None and sys.platform.startswith(('linux', 'darwin')): # [4.0] ensure window not covered on Linux and Mac OS X (Windows ok) self.wait_visibility() self.transient(parent) 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, parent): pass if __name__ == '__main__': HelpPopup('spam', 'See figure 1...\n') print(askPasswordWindow('spam', 'enter password')) input('Enter to exit') # pause if clicked