blob: 01709d8103afc6b24f6a46b6d512071a562eef2e [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
Fred Drake6b04ffe2001-12-06 16:51:41 +000071 if self.parent is not None:
72 self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
73 parent.winfo_rooty()+50))
Guido van Rossumf55afae1997-08-12 18:21:21 +000074
75 self.initial_focus.focus_set()
76
77 self.wait_window(self)
78
Guido van Rossum7ea8f841999-06-25 15:53:54 +000079 def destroy(self):
Guido van Rossumd5062ba2000-02-24 15:01:43 +000080 '''Destroy the window'''
Guido van Rossum7ea8f841999-06-25 15:53:54 +000081 self.initial_focus = None
82 Toplevel.destroy(self)
83
Guido van Rossumf55afae1997-08-12 18:21:21 +000084 #
85 # construction hooks
86
87 def body(self, master):
Guido van Rossumd5062ba2000-02-24 15:01:43 +000088 '''create dialog body.
Guido van Rossumf55afae1997-08-12 18:21:21 +000089
Fred Draked038ca82000-10-23 18:31:14 +000090 return widget that should have initial focus.
Guido van Rossumd5062ba2000-02-24 15:01:43 +000091 This method should be overridden, and is called
92 by the __init__ method.
93 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +000094 pass
95
96 def buttonbox(self):
Fred Draked038ca82000-10-23 18:31:14 +000097 '''add standard button box.
Guido van Rossumd5062ba2000-02-24 15:01:43 +000098
Fred Drake6b04ffe2001-12-06 16:51:41 +000099 override if you do not want the standard buttons
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000100 '''
Fred Draked038ca82000-10-23 18:31:14 +0000101
Guido van Rossumf55afae1997-08-12 18:21:21 +0000102 box = Frame(self)
103
104 w = Button(box, text="OK", width=10, command=self.ok, default=ACTIVE)
105 w.pack(side=LEFT, padx=5, pady=5)
106 w = Button(box, text="Cancel", width=10, command=self.cancel)
107 w.pack(side=LEFT, padx=5, pady=5)
108
109 self.bind("<Return>", self.ok)
110 self.bind("<Escape>", self.cancel)
111
112 box.pack()
113
114 #
115 # standard button semantics
116
117 def ok(self, event=None):
118
119 if not self.validate():
120 self.initial_focus.focus_set() # put focus back
121 return
122
123 self.withdraw()
124 self.update_idletasks()
125
126 self.apply()
127
128 self.cancel()
129
130 def cancel(self, event=None):
131
132 # put focus back to the parent window
Fred Drake6b04ffe2001-12-06 16:51:41 +0000133 if self.parent is not None:
134 self.parent.focus_set()
Guido van Rossumf55afae1997-08-12 18:21:21 +0000135 self.destroy()
136
137 #
138 # command hooks
139
140 def validate(self):
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000141 '''validate the data
142
Fred Draked038ca82000-10-23 18:31:14 +0000143 This method is called automatically to validate the data before the
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000144 dialog is destroyed. By default, it always validates OK.
145 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +0000146
147 return 1 # override
148
149 def apply(self):
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000150 '''process the data
151
152 This method is called automatically to process the data, *after*
153 the dialog is destroyed. By default, it does nothing.
154 '''
Guido van Rossumf55afae1997-08-12 18:21:21 +0000155
156 pass # override
157
158
159# --------------------------------------------------------------------
160# convenience dialogues
161
Guido van Rossumf55afae1997-08-12 18:21:21 +0000162class _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
Fred Draked038ca82000-10-23 18:31:14 +0000230
Guido van Rossumf55afae1997-08-12 18:21:21 +0000231 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):
Eric S. Raymondfc170b12001-02-09 11:51:27 +0000239 return int(self.entry.get())
Guido van Rossumf55afae1997-08-12 18:21:21 +0000240
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 '''
Raymond Hettingerff41c482003-04-06 09:01:11 +0000252 d = _QueryInteger(title, prompt, **kw)
Guido van Rossumf55afae1997-08-12 18:21:21 +0000253 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):
Eric S. Raymondfc170b12001-02-09 11:51:27 +0000258 return float(self.entry.get())
Guido van Rossumf55afae1997-08-12 18:21:21 +0000259
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 '''
Raymond Hettingerff41c482003-04-06 09:01:11 +0000271 d = _QueryFloat(title, prompt, **kw)
Guido van Rossumf55afae1997-08-12 18:21:21 +0000272 return d.result
273
274class _QueryString(_QueryDialog):
Fred Drake6b04ffe2001-12-06 16:51:41 +0000275 def __init__(self, *args, **kw):
276 if kw.has_key("show"):
277 self.__show = kw["show"]
278 del kw["show"]
279 else:
280 self.__show = None
281 _QueryDialog.__init__(self, *args, **kw)
282
283 def body(self, master):
284 entry = _QueryDialog.body(self, master)
285 if self.__show is not None:
286 entry.configure(show=self.__show)
287 return entry
288
Guido van Rossumf55afae1997-08-12 18:21:21 +0000289 def getresult(self):
290 return self.entry.get()
291
292def askstring(title, prompt, **kw):
Guido van Rossumd5062ba2000-02-24 15:01:43 +0000293 '''get a string from the user
294
295 Arguments:
296
297 title -- the dialog title
298 prompt -- the label text
299 **kw -- see SimpleDialog class
300
301 Return value is a string
302 '''
Raymond Hettingerff41c482003-04-06 09:01:11 +0000303 d = _QueryString(title, prompt, **kw)
Guido van Rossumf55afae1997-08-12 18:21:21 +0000304 return d.result
305
Fred Draked038ca82000-10-23 18:31:14 +0000306if __name__ == "__main__":
Guido van Rossumf55afae1997-08-12 18:21:21 +0000307
308 root = Tk()
309 root.update()
310
Guido van Rossum1530c871997-08-14 14:17:28 +0000311 print askinteger("Spam", "Egg count", initialvalue=12*12)
312 print askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100)
Guido van Rossumf55afae1997-08-12 18:21:21 +0000313 print askstring("Spam", "Egg label")