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