#
# An Introduction to Tkinter
# tkSimpleDialog.py
#
# Copyright (c) 1997 by Fredrik Lundh
#
# fredrik@pythonware.com
# http://www.pythonware.com
#
# Modified by Thanasis Stamos Aug 12, 2004
# 1. Nested grab_set were implemented
# 2. The gepmetry manager was changes to grid
# --------------------------------------------------------------------
# dialog base class
'''Dialog boxes
This module handles dialog boxes. It contains the following
public symbols:
Dialog -- a base class for dialogs
askinteger -- get an integer from theuser import
askfloat -- get a float from theuser import
askstring -- get a string from theuser import
'''
from Tkinter import *
import os
from thantkutilb import thanGrabSet# Stamos Aug 12, 2004
class ThanDialog(Toplevel):
'''Class to open dialogs.
This class is intended as a base class for custom dialogs
'''
# def __init__(self, parent, title = None):
def __init__(self, parent, title=None, buttonlabels=("OK", "Cancel", "Apply"), **kw): # Stamos Aug 12, 2004
'''Initialize a dialog.
Arguments:
parent -- a parent window (the application window)
title -- the dialog title
'''
self._butLabs = buttonlabels # Stamos 2007_03_21
Toplevel.__init__(self, parent, **kw)
if parent is not None:
self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
parent.winfo_rooty()+50))
if title: self.title(title)
body = Frame(self)
self.initial_focus = self.body(body)
body.grid(padx=5, pady=5, sticky="wesn") # Stamos Aug 12, 2004
if not self.initial_focus: self.initial_focus = self
self.buttonbox()
self.columnconfigure(0, weight=1) # Stamos Aug 12, 2004
self.rowconfigure(0, weight=1) # Stamos Aug 12, 2004
self.transient(parent)
# self.grab_set()
thanGrabSet(self) # Stamos Aug 12, 2004
self.protocol("WM_DELETE_WINDOW", self.cancel)
# if parent is not None:
# self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
# parent.winfo_rooty()+50))
self.initial_focus.focus_set()
self.parent = parent
self.result = None
self.wait_window(self)
def thanRePos(self, master=None): # Stamos Jul 21, 2005
"Position this dialog centered over its master."
siz, xm, ym = master.winfo_toplevel().geometry().split("+")
wm, hm = siz.split("x")
self.update_idletasks()
siz, x, y = self.geometry().split("+")
w, h = siz.split("x")
x = int(xm) + int( (int(wm)-int(w))/2 )
if x < 0: x = 0
y = int(ym) + int( (int(hm)-int(h))/2 )
if y < 0: y = 0
self.geometry("%+d%+d" % (x, y))
def destroy(self):
'''Destroy the window'''
self.initial_focus = None
self.parent = None
# self.grab_release() # Stamos Nov 28, 2006: commented out
Toplevel.destroy(self)
#
# construction hooks
def body(self, master):
'''create dialog body.
return widget that should have initial focus.
This method should be overridden, and is called
by the __init__ method.
'''
pass
def buttonbox(self):
'''add standard button box.
override if you do not want the standard buttons
'''
box = Frame(self)
w = Button(box, text=self._butLabs[0], bg="lightgreen", activebackground="green", # Stamos 2007_03_21
width=10, command=self.ok, default=ACTIVE) # Stamos Feb 26, 2006
w.grid(row=0, column=0, padx=5, pady=5, sticky="w") # Stamos Aug 12, 2004
w = Button(box, text=self._butLabs[1], bg="pink", activebackground="red", # Stamos 2007_03_21
width=10, command=self.cancel) # Stamos Feb 26, 2006
w.grid(row=0, column=1, padx=5, pady=5, sticky="e") # Stamos Aug 12, 2004
self.bind("<Return>", self.ok)
self.bind("<Escape>", self.cancel)
box.grid(sticky="wesn") # Stamos Aug 12, 2004
box.columnconfigure(0, weight=1) # Stamos Aug 12, 2004
box.columnconfigure(1, weight=1) # Stamos Aug 12, 2004
#
# standard button semantics
def ok(self, event=None):
if not self.validate():
self.initial_focus.focus_set() # put focus back
return False
self.withdraw()
self.update_idletasks()
self.apply()
# put focus back to the parent window
if self.parent is not None:
self.parent.focus_set()
self.destroy()
def cancel(self, event=None):
# put focus back to the parent window
if self.parent is not None:
self.parent.focus_set()
self.result = None
self.destroy()
#
# command hooks
def validate(self):
'''validate the data
This method is called automatically to validate the data before the
dialog is destroyed. By default, it always validates OK.
'''
return 1 # override
def apply(self):
'''process the data
This method is called automatically to process the data, *after*
the dialog is destroyed. By default, it does nothing.
'''
pass # override
class ThanDialog3(ThanDialog):
"Adds a new standard button: apply."
def buttonbox(self):
'''add standard button box.
override if you do not want the standard buttons
'''
box = Frame(self)
w = Button(box, text=self._butLabs[0], bg="lightgreen", activebackground="green", # Stamos 2007_03_21
width=10, command=self.ok, default=ACTIVE) # Stamos Feb 26, 2006
w.grid(row=0, column=0, padx=5, pady=5, sticky="w") # Stamos Aug 12, 2004
w = Button(box, text=self._butLabs[2], bg="gold", activebackground="yellow", # Stamos 2007_03_21
width=10, command=self.doApply) # Stamos Feb 26, 2006
w.grid(row=0, column=1, padx=5, pady=5, sticky="w") # Stamos Jul 15, 2005
w = Button(box, text=self._butLabs[1], bg="pink", activebackground="red", # Stamos 2007_03_21
width=10, command=self.cancel) # Stamos Feb 26, 2006
w.grid(row=0, column=2, padx=5, pady=5, sticky="e") # Stamos Aug 12, 2004
self.bind("<Return>", self.ok)
self.bind("<Escape>", self.cancel)
box.grid(sticky="wesn") # Stamos Aug 12, 2004
box.columnconfigure(0, weight=1) # Stamos Aug 12, 2004
box.columnconfigure(1, weight=1) # Stamos Aug 12, 2004
def doApply(self, *args):
if not self.validate():
self.initial_focus.focus_set() # put focus back
return False
return True
# --------------------------------------------------------------------
# convenience dialogues
class _QueryDialog(ThanDialog):
def __init__(self, title, prompt,
initialvalue=None,
minvalue = None, maxvalue = None,
parent = None):
if not parent:
import Tkinter
parent = Tkinter._default_root
self.prompt = prompt
self.minvalue = minvalue
self.maxvalue = maxvalue
self.initialvalue = initialvalue
ThanDialog.__init__(self, parent, title)
def destroy(self):
self.entry = None
ThanDialog.destroy(self)
def body(self, master):
w = Label(master, text=self.prompt, justify=LEFT)
w.grid(row=0, padx=5, sticky=W)
self.entry = Entry(master, name="entry")
self.entry.grid(row=1, padx=5, sticky=W+E)
if self.initialvalue:
self.entry.insert(0, self.initialvalue)
self.entry.select_range(0, END)
return self.entry
def validate(self):
import tkMessageBox
try:
result = self.getresult()
except ValueError:
tkMessageBox.showwarning(
"Illegal value",
self.errormessage + "\nPlease try again",
parent = self
)
return 0
if self.minvalue is not None and result < self.minvalue:
tkMessageBox.showwarning(
"Too small",
"The allowed minimum value is %s. "
"Please try again." % self.minvalue,
parent = self
)
return 0
if self.maxvalue is not None and result > self.maxvalue:
tkMessageBox.showwarning(
"Too large",
"The allowed maximum value is %s. "
"Please try again." % self.maxvalue,
parent = self
)
return 0
self.result = result
return 1
class _QueryInteger(_QueryDialog):
errormessage = "Not an integer."
def getresult(self):
return int(self.entry.get())
def askinteger(title, prompt, **kw):
'''get an integer from theuser import
Arguments:
title -- the dialog title
prompt -- the label text
**kw -- see SimpleDialog class
Return value is an integer
'''
d = _QueryInteger(title, prompt, **kw)
return d.result
class _QueryFloat(_QueryDialog):
errormessage = "Not a floating point value."
def getresult(self):
return float(self.entry.get())
def askfloat(title, prompt, **kw):
'''get a float from theuser import
Arguments:
title -- the dialog title
prompt -- the label text
**kw -- see SimpleDialog class
Return value is a float
'''
d = _QueryFloat(title, prompt, **kw)
return d.result
class _QueryString(_QueryDialog):
def __init__(self, *args, **kw):
if kw.has_key("show"):
self.__show = kw["show"]
del kw["show"]
else:
self.__show = None
_QueryDialog.__init__(self, *args, **kw)
def body(self, master):
entry = _QueryDialog.body(self, master)
if self.__show is not None:
entry.configure(show=self.__show)
return entry
def getresult(self):
return self.entry.get()
def askstring(title, prompt, **kw):
'''get a string from theuser import
Arguments:
title -- the dialog title
prompt -- the label text
**kw -- see SimpleDialog class
Return value is a string
'''
d = _QueryString(title, prompt, **kw)
return d.result
if __name__ == "__main__":
root = Tk()
root.update()
print askinteger("Spam", "Egg count", initialvalue=12*12)
print askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100)
print askstring("Spam", "Egg label")
|