Issue #7084: Fix a (very unlikely) crash when printing a list from one
[python.git] / Lib / lib-tk / tkSimpleDialog.py
blob24388a5e0dc689e71129b5c0d01e398c9198924f
2 # An Introduction to Tkinter
3 # tkSimpleDialog.py
5 # Copyright (c) 1997 by Fredrik Lundh
7 # fredrik@pythonware.com
8 # http://www.pythonware.com
11 # --------------------------------------------------------------------
12 # dialog base class
14 '''Dialog boxes
16 This module handles dialog boxes. It contains the following
17 public symbols:
19 Dialog -- a base class for dialogs
21 askinteger -- get an integer from the user
23 askfloat -- get a float from the user
25 askstring -- get a string from the user
26 '''
28 from Tkinter import *
30 class Dialog(Toplevel):
32 '''Class to open dialogs.
34 This class is intended as a base class for custom dialogs
35 '''
37 def __init__(self, parent, title = None):
39 '''Initialize a dialog.
41 Arguments:
43 parent -- a parent window (the application window)
45 title -- the dialog title
46 '''
47 Toplevel.__init__(self, parent)
49 self.withdraw() # remain invisible for now
50 # If the master is not viewable, don't
51 # make the child transient, or else it
52 # would be opened withdrawn
53 if parent.winfo_viewable():
54 self.transient(parent)
56 if title:
57 self.title(title)
59 self.parent = parent
61 self.result = None
63 body = Frame(self)
64 self.initial_focus = self.body(body)
65 body.pack(padx=5, pady=5)
67 self.buttonbox()
70 if not self.initial_focus:
71 self.initial_focus = self
73 self.protocol("WM_DELETE_WINDOW", self.cancel)
75 if self.parent is not None:
76 self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
77 parent.winfo_rooty()+50))
79 self.deiconify() # become visibile now
81 self.initial_focus.focus_set()
83 # wait for window to appear on screen before calling grab_set
84 self.wait_visibility()
85 self.grab_set()
86 self.wait_window(self)
88 def destroy(self):
89 '''Destroy the window'''
90 self.initial_focus = None
91 Toplevel.destroy(self)
94 # construction hooks
96 def body(self, master):
97 '''create dialog body.
99 return widget that should have initial focus.
100 This method should be overridden, and is called
101 by the __init__ method.
103 pass
105 def buttonbox(self):
106 '''add standard button box.
108 override if you do not want the standard buttons
111 box = Frame(self)
113 w = Button(box, text="OK", width=10, command=self.ok, default=ACTIVE)
114 w.pack(side=LEFT, padx=5, pady=5)
115 w = Button(box, text="Cancel", width=10, command=self.cancel)
116 w.pack(side=LEFT, padx=5, pady=5)
118 self.bind("<Return>", self.ok)
119 self.bind("<Escape>", self.cancel)
121 box.pack()
124 # standard button semantics
126 def ok(self, event=None):
128 if not self.validate():
129 self.initial_focus.focus_set() # put focus back
130 return
132 self.withdraw()
133 self.update_idletasks()
135 try:
136 self.apply()
137 finally:
138 self.cancel()
140 def cancel(self, event=None):
142 # put focus back to the parent window
143 if self.parent is not None:
144 self.parent.focus_set()
145 self.destroy()
148 # command hooks
150 def validate(self):
151 '''validate the data
153 This method is called automatically to validate the data before the
154 dialog is destroyed. By default, it always validates OK.
157 return 1 # override
159 def apply(self):
160 '''process the data
162 This method is called automatically to process the data, *after*
163 the dialog is destroyed. By default, it does nothing.
166 pass # override
169 # --------------------------------------------------------------------
170 # convenience dialogues
172 class _QueryDialog(Dialog):
174 def __init__(self, title, prompt,
175 initialvalue=None,
176 minvalue = None, maxvalue = None,
177 parent = None):
179 if not parent:
180 import Tkinter
181 parent = Tkinter._default_root
183 self.prompt = prompt
184 self.minvalue = minvalue
185 self.maxvalue = maxvalue
187 self.initialvalue = initialvalue
189 Dialog.__init__(self, parent, title)
191 def destroy(self):
192 self.entry = None
193 Dialog.destroy(self)
195 def body(self, master):
197 w = Label(master, text=self.prompt, justify=LEFT)
198 w.grid(row=0, padx=5, sticky=W)
200 self.entry = Entry(master, name="entry")
201 self.entry.grid(row=1, padx=5, sticky=W+E)
203 if self.initialvalue:
204 self.entry.insert(0, self.initialvalue)
205 self.entry.select_range(0, END)
207 return self.entry
209 def validate(self):
211 import tkMessageBox
213 try:
214 result = self.getresult()
215 except ValueError:
216 tkMessageBox.showwarning(
217 "Illegal value",
218 self.errormessage + "\nPlease try again",
219 parent = self
221 return 0
223 if self.minvalue is not None and result < self.minvalue:
224 tkMessageBox.showwarning(
225 "Too small",
226 "The allowed minimum value is %s. "
227 "Please try again." % self.minvalue,
228 parent = self
230 return 0
232 if self.maxvalue is not None and result > self.maxvalue:
233 tkMessageBox.showwarning(
234 "Too large",
235 "The allowed maximum value is %s. "
236 "Please try again." % self.maxvalue,
237 parent = self
239 return 0
241 self.result = result
243 return 1
246 class _QueryInteger(_QueryDialog):
247 errormessage = "Not an integer."
248 def getresult(self):
249 return int(self.entry.get())
251 def askinteger(title, prompt, **kw):
252 '''get an integer from the user
254 Arguments:
256 title -- the dialog title
257 prompt -- the label text
258 **kw -- see SimpleDialog class
260 Return value is an integer
262 d = _QueryInteger(title, prompt, **kw)
263 return d.result
265 class _QueryFloat(_QueryDialog):
266 errormessage = "Not a floating point value."
267 def getresult(self):
268 return float(self.entry.get())
270 def askfloat(title, prompt, **kw):
271 '''get a float from the user
273 Arguments:
275 title -- the dialog title
276 prompt -- the label text
277 **kw -- see SimpleDialog class
279 Return value is a float
281 d = _QueryFloat(title, prompt, **kw)
282 return d.result
284 class _QueryString(_QueryDialog):
285 def __init__(self, *args, **kw):
286 if "show" in kw:
287 self.__show = kw["show"]
288 del kw["show"]
289 else:
290 self.__show = None
291 _QueryDialog.__init__(self, *args, **kw)
293 def body(self, master):
294 entry = _QueryDialog.body(self, master)
295 if self.__show is not None:
296 entry.configure(show=self.__show)
297 return entry
299 def getresult(self):
300 return self.entry.get()
302 def askstring(title, prompt, **kw):
303 '''get a string from the user
305 Arguments:
307 title -- the dialog title
308 prompt -- the label text
309 **kw -- see SimpleDialog class
311 Return value is a string
313 d = _QueryString(title, prompt, **kw)
314 return d.result
316 if __name__ == "__main__":
318 root = Tk()
319 root.update()
321 print askinteger("Spam", "Egg count", initialvalue=12*12)
322 print askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100)
323 print askstring("Spam", "Egg label")