blob: 395a369f9740b70a612889234d902dd1416d2259 [file] [log] [blame]
Guido van Rossumf55afae1997-08-12 18:21:21 +00001#
2# An Introduction to Tkinter
3# tkSimpleDialog.py
4#
5# Copyright (c) 1997 by Fredrik Lundh
6#
7# fredrik@pythonware.com
8# http://www.pythonware.com
9#
10
11# --------------------------------------------------------------------
12# dialog base class
13
Guido van Rossumd5062ba2000-02-24 15:01:43 +000014'''Dialog boxes
15
16This module handles dialog boxes. It contains the following
17public symbols:
18
19Dialog -- a base class for dialogs
20
21askinteger -- get an integer from the user
22
23askfloat -- get a float from the user
24
25askstring -- get a string from the user
26'''
27
Guido van Rossumf55afae1997-08-12 18:21:21 +000028from Tkinter import *
29import os
30
31class Dialog(Toplevel):
32
Guido van Rossumd5062ba2000-02-24 15:01:43 +000033 '''Class to open dialogs.
34
35 This class is intended as a base class for custom dialogs
36 '''
37
Guido van Rossumf55afae1997-08-12 18:21:21 +000038 def __init__(self, parent, title = None):
39
Guido van Rossumd5062ba2000-02-24 15:01:43 +000040 '''Initialize a dialog.
41
42 Arguments:
43
44 parent -- a parent window (the application window)
45
46 title -- the dialog title
47 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +000048 Toplevel.__init__(self, parent)
49 self.transient(parent)
50
51 if title:
52 self.title(title)
53
54 self.parent = parent
55
56 self.result = None
57
58 body = Frame(self)
59 self.initial_focus = self.body(body)
60 body.pack(padx=5, pady=5)
61
62 self.buttonbox()
63
64 self.grab_set()
65
66 if not self.initial_focus:
67 self.initial_focus = self
68
69 self.protocol("WM_DELETE_WINDOW", self.cancel)
70
71 self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
72 parent.winfo_rooty()+50))
73
74 self.initial_focus.focus_set()
75
76 self.wait_window(self)
77
Guido van Rossum7ea8f841999-06-25 15:53:54 +000078 def destroy(self):
Guido van Rossumd5062ba2000-02-24 15:01:43 +000079 '''Destroy the window'''
Guido van Rossum7ea8f841999-06-25 15:53:54 +000080 self.initial_focus = None
81 Toplevel.destroy(self)
82
Guido van Rossumf55afae1997-08-12 18:21:21 +000083 #
84 # construction hooks
85
86 def body(self, master):
Guido van Rossumd5062ba2000-02-24 15:01:43 +000087 '''create dialog body.
Guido van Rossumf55afae1997-08-12 18:21:21 +000088
Guido van Rossumd5062ba2000-02-24 15:01:43 +000089 return widget that should have initial focus.
90 This method should be overridden, and is called
91 by the __init__ method.
92 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +000093 pass
94
95 def buttonbox(self):
Guido van Rossumd5062ba2000-02-24 15:01:43 +000096 '''add standard button box.
97
98 override if you don't want the standard buttons
99 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +0000100
101 box = Frame(self)
102
103 w = Button(box, text="OK", width=10, command=self.ok, default=ACTIVE)
104 w.pack(side=LEFT, padx=5, pady=5)
105 w = Button(box, text="Cancel", width=10, command=self.cancel)
106 w.pack(side=LEFT, padx=5, pady=5)
107
108 self.bind("<Return>", self.ok)
109 self.bind("<Escape>", self.cancel)
110
111 box.pack()
112
113 #
114 # standard button semantics
115
116 def ok(self, event=None):
117
118 if not self.validate():
119 self.initial_focus.focus_set() # put focus back
120 return
121
122 self.withdraw()
123 self.update_idletasks()
124
125 self.apply()
126
127 self.cancel()
128
129 def cancel(self, event=None):
130
131 # put focus back to the parent window
132 self.parent.focus_set()
133 self.destroy()
134
135 #
136 # command hooks
137
138 def validate(self):
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000139 '''validate the data
140
141 This method is called automatically to validate the data before the
142 dialog is destroyed. By default, it always validates OK.
143 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +0000144
145 return 1 # override
146
147 def apply(self):
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000148 '''process the data
149
150 This method is called automatically to process the data, *after*
151 the dialog is destroyed. By default, it does nothing.
152 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +0000153
154 pass # override
155
156
157# --------------------------------------------------------------------
158# convenience dialogues
159
160import string
161
162class _QueryDialog(Dialog):
163
164 def __init__(self, title, prompt,
Guido van Rossum1530c871997-08-14 14:17:28 +0000165 initialvalue=None,
Guido van Rossumf55afae1997-08-12 18:21:21 +0000166 minvalue = None, maxvalue = None,
167 parent = None):
168
Guido van Rossumf55afae1997-08-12 18:21:21 +0000169 if not parent:
Guido van Rossum7f202631998-10-12 20:40:09 +0000170 import Tkinter
171 parent = Tkinter._default_root
Guido van Rossumf55afae1997-08-12 18:21:21 +0000172
173 self.prompt = prompt
174 self.minvalue = minvalue
175 self.maxvalue = maxvalue
176
Guido van Rossum1530c871997-08-14 14:17:28 +0000177 self.initialvalue = initialvalue
178
Guido van Rossumf55afae1997-08-12 18:21:21 +0000179 Dialog.__init__(self, parent, title)
180
Guido van Rossum7ea8f841999-06-25 15:53:54 +0000181 def destroy(self):
182 self.entry = None
183 Dialog.destroy(self)
184
Guido van Rossumf55afae1997-08-12 18:21:21 +0000185 def body(self, master):
186
Guido van Rossum1530c871997-08-14 14:17:28 +0000187 w = Label(master, text=self.prompt, justify=LEFT)
Guido van Rossumf55afae1997-08-12 18:21:21 +0000188 w.grid(row=0, padx=5, sticky=W)
189
190 self.entry = Entry(master, name="entry")
191 self.entry.grid(row=1, padx=5, sticky=W+E)
192
Guido van Rossum1530c871997-08-14 14:17:28 +0000193 if self.initialvalue:
194 self.entry.insert(0, self.initialvalue)
195 self.entry.select_range(0, END)
196
Guido van Rossumf55afae1997-08-12 18:21:21 +0000197 return self.entry
198
199 def validate(self):
200
201 import tkMessageBox
202
203 try:
204 result = self.getresult()
205 except ValueError:
206 tkMessageBox.showwarning(
Guido van Rossum1530c871997-08-14 14:17:28 +0000207 "Illegal value",
Guido van Rossumf55afae1997-08-12 18:21:21 +0000208 self.errormessage + "\nPlease try again",
209 parent = self
210 )
211 return 0
212
213 if self.minvalue is not None and result < self.minvalue:
214 tkMessageBox.showwarning(
215 "Too small",
216 "The allowed minimum value is %s. "
Guido van Rossum1530c871997-08-14 14:17:28 +0000217 "Please try again." % self.minvalue,
Guido van Rossumf55afae1997-08-12 18:21:21 +0000218 parent = self
219 )
220 return 0
221
222 if self.maxvalue is not None and result > self.maxvalue:
223 tkMessageBox.showwarning(
Guido van Rossum1530c871997-08-14 14:17:28 +0000224 "Too large",
Guido van Rossumf55afae1997-08-12 18:21:21 +0000225 "The allowed maximum value is %s. "
Guido van Rossum1530c871997-08-14 14:17:28 +0000226 "Please try again." % self.maxvalue,
Guido van Rossumf55afae1997-08-12 18:21:21 +0000227 parent = self
228 )
229 return 0
230
231 self.result = result
232
233 return 1
234
235
236class _QueryInteger(_QueryDialog):
Guido van Rossum1530c871997-08-14 14:17:28 +0000237 errormessage = "Not an integer."
Guido van Rossumf55afae1997-08-12 18:21:21 +0000238 def getresult(self):
239 return string.atoi(self.entry.get())
240
241def askinteger(title, prompt, **kw):
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000242 '''get an integer from the user
243
244 Arguments:
245
246 title -- the dialog title
247 prompt -- the label text
248 **kw -- see SimpleDialog class
249
250 Return value is an integer
251 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +0000252 d = apply(_QueryInteger, (title, prompt), kw)
253 return d.result
254
255class _QueryFloat(_QueryDialog):
Guido van Rossum1530c871997-08-14 14:17:28 +0000256 errormessage = "Not a floating point value."
Guido van Rossumf55afae1997-08-12 18:21:21 +0000257 def getresult(self):
258 return string.atof(self.entry.get())
259
260def askfloat(title, prompt, **kw):
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000261 '''get a float from the user
262
263 Arguments:
264
265 title -- the dialog title
266 prompt -- the label text
267 **kw -- see SimpleDialog class
268
269 Return value is a float
270 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +0000271 d = apply(_QueryFloat, (title, prompt), kw)
272 return d.result
273
274class _QueryString(_QueryDialog):
275 def getresult(self):
276 return self.entry.get()
277
278def askstring(title, prompt, **kw):
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000279 '''get a string from the user
280
281 Arguments:
282
283 title -- the dialog title
284 prompt -- the label text
285 **kw -- see SimpleDialog class
286
287 Return value is a string
288 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +0000289 d = apply(_QueryString, (title, prompt), kw)
290 return d.result
291
292if __name__ == "__main__":
293
294 root = Tk()
295 root.update()
296
Guido van Rossum1530c871997-08-14 14:17:28 +0000297 print askinteger("Spam", "Egg count", initialvalue=12*12)
298 print askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100)
Guido van Rossumf55afae1997-08-12 18:21:21 +0000299 print askstring("Spam", "Egg label")
Guido van Rossum1530c871997-08-14 14:17:28 +0000300