| #! /usr/bin/env python |
| |
| # A Python function that generates dialog boxes with a text message, |
| # optional bitmap, and any number of buttons. |
| # Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270. |
| |
| from Tkinter import * |
| |
| mainWidget = None |
| |
| def dialog(master, title, text, bitmap, default, *args): |
| |
| # 1. Create the top-level window and divide it into top |
| # and bottom parts. |
| |
| w = Toplevel(master, {'class': 'Dialog'}) |
| w.title(title) |
| w.iconname('Dialog') |
| |
| top = Frame(w, {'relief': 'raised', 'bd': 1, |
| Pack: {'side': 'top', 'fill': 'both'}}) |
| bot = Frame(w, {'relief': 'raised', 'bd': 1, |
| Pack: {'side': 'bottom', 'fill': 'both'}}) |
| |
| # 2. Fill the top part with the bitmap and message. |
| |
| msg = Message(top, |
| {'width': '3i', |
| 'text': text, |
| 'font': '-Adobe-Times-Medium-R-Normal-*-180-*', |
| Pack: {'side': 'right', 'expand': 1, |
| 'fill': 'both', |
| 'padx': '3m', 'pady': '3m'}}) |
| if bitmap: |
| bm = Label(top, {'bitmap': bitmap, |
| Pack: {'side': 'left', |
| 'padx': '3m', 'pady': '3m'}}) |
| |
| # 3. Create a row of buttons at the bottom of the dialog. |
| |
| buttons = [] |
| i = 0 |
| for but in args: |
| b = Button(bot, {'text': but, |
| 'command': ('set', 'button', i)}) |
| buttons.append(b) |
| if i == default: |
| bd = Frame(bot, {'relief': 'sunken', 'bd': 1, |
| Pack: {'side': 'left', 'expand': 1, |
| 'padx': '3m', 'pady': '2m'}}) |
| b.lift() |
| b.pack ({'in': bd, 'side': 'left', |
| 'padx': '2m', 'pady': '2m', |
| 'ipadx': '2m', 'ipady': '1m'}) |
| else: |
| b.pack ({'side': 'left', 'expand': 1, |
| 'padx': '3m', 'pady': '3m', |
| 'ipady': '2m', 'ipady': '1m'}) |
| i = i+1 |
| |
| # 4. Set up a binding for <Return>, if there's a default, |
| # set a grab, and claim the focus too. |
| |
| if default >= 0: |
| w.bind('<Return>', |
| lambda e, b=buttons[default], i=default: |
| (b.flash(), |
| b.setvar('button', i))) |
| |
| oldFocus = w.tk.call('focus') # XXX |
| w.grab_set() |
| w.focus() |
| |
| # 5. Wait for the user to respond, then restore the focus |
| # and return the index of the selected button. |
| |
| w.waitvar('button') |
| w.destroy() |
| w.tk.call('focus', oldFocus) # XXX |
| return w.getint(w.getvar('button')) |
| |
| def strdialog(master, title, text, bitmap, default, *args): |
| |
| # 1. Create the top-level window and divide it into top |
| # and bottom parts. |
| |
| w = Toplevel(master, {'class': 'Dialog'}) |
| w.title(title) |
| w.iconname('Dialog') |
| |
| top = Frame(w, {'relief': 'raised', 'bd': 1, |
| Pack: {'side': 'top', 'fill': 'both'}}) |
| if args: |
| bot = Frame(w, {'relief': 'raised', 'bd': 1, |
| Pack: {'side': 'bottom', 'fill': 'both'}}) |
| |
| # 2. Fill the top part with the bitmap, message and input field. |
| |
| if bitmap: |
| bm = Label(top, {'bitmap': bitmap, |
| Pack: {'side': 'left', |
| 'padx': '3m', 'pady': '3m'}}) |
| |
| msg = Message(top, |
| {'width': '3i', |
| 'text': text, |
| 'font': '-Adobe-Times-Medium-R-Normal-*-180-*', |
| Pack: {'side': 'left', |
| 'fill': 'both', |
| 'padx': '3m', 'pady': '3m'}}) |
| |
| field = Entry(top, |
| {'relief':'sunken', |
| Pack:{'side':'left', |
| 'fill':'x', |
| 'expand':1, |
| 'padx':'3m', 'pady':'3m'}}) |
| # 3. Create a row of buttons at the bottom of the dialog. |
| |
| buttons = [] |
| i = 0 |
| for but in args: |
| b = Button(bot, {'text': but, |
| 'command': ('set', 'button', i)}) |
| buttons.append(b) |
| if i == default: |
| bd = Frame(bot, {'relief': 'sunken', 'bd': 1, |
| Pack: {'side': 'left', 'expand': 1, |
| 'padx': '3m', 'pady': '2m'}}) |
| b.lift() |
| b.pack ({'in': bd, 'side': 'left', |
| 'padx': '2m', 'pady': '2m', |
| 'ipadx': '2m', 'ipady': '1m'}) |
| else: |
| b.pack ({'side': 'left', 'expand': 1, |
| 'padx': '3m', 'pady': '3m', |
| 'ipady': '2m', 'ipady': '1m'}) |
| i = i+1 |
| |
| # 4. Set up a binding for <Return>, if there's a default, |
| # set a grab, and claim the focus too. |
| |
| if not args: |
| w.bind('<Return>', lambda arg, top=top: top.setvar('button', 0)) |
| field.bind('<Return>', lambda arg, top=top: top.setvar('button', 0)) |
| elif default >= 0: |
| w.bind('<Return>', |
| lambda e, b=buttons[default], i=default: |
| (b.flash(), |
| b.setvar('button', i))) |
| field.bind('<Return>', |
| lambda e, b=buttons[default], i=default: |
| (b.flash(), |
| b.setvar('button', i))) |
| |
| oldFocus = w.tk.call('focus') # XXX |
| w.grab_set() |
| field.focus() |
| |
| # 5. Wait for the user to respond, then restore the focus |
| # and return the index of the selected button. |
| |
| w.waitvar('button') |
| v = field.get() |
| w.destroy() |
| w.tk.call('focus', oldFocus) # XXX |
| if args: |
| return v, w.getint(w.getvar('button')) |
| else: |
| return v |
| |
| def message(str): |
| i = dialog(mainWidget, 'Message', str, '', 0, 'OK') |
| |
| def askyn(str): |
| i = dialog(mainWidget, 'Question', str, '', 0, 'No', 'Yes') |
| return i |
| |
| def askync(str): |
| i = dialog(mainWidget, 'Question', str, '', 0, 'Cancel', 'No', 'Yes') |
| return i-1 |
| |
| def askstr(str): |
| i = strdialog(mainWidget, 'Question', str, '', 0) |
| return i |
| |
| def askfile(str): # XXXX For now... |
| i = strdialog(mainWidget, 'Question', str, '', 0) |
| return i |
| |
| # The rest is the test program. |
| |
| def _go(): |
| i = dialog(mainWidget, |
| 'Not Responding', |
| "The file server isn't responding right now; " |
| "I'll keep trying.", |
| '', |
| -1, |
| 'OK') |
| print 'pressed button', i |
| i = dialog(mainWidget, |
| 'File Modified', |
| 'File "tcl.h" has been modified since ' |
| 'the last time it was saved. ' |
| 'Do you want to save it before exiting the application?', |
| 'warning', |
| 0, |
| 'Save File', |
| 'Discard Changes', |
| 'Return To Editor') |
| print 'pressed button', i |
| print message('Test of message') |
| print askyn('Test of yes/no') |
| print askync('Test of yes/no/cancel') |
| print askstr('Type a string:') |
| print strdialog(mainWidget, 'Question', 'Another string:', '', |
| 0, 'Save', 'Save as text') |
| |
| def _test(): |
| import sys |
| global mainWidget |
| mainWidget = Frame() |
| Pack.config(mainWidget) |
| start = Button(mainWidget, |
| {'text': 'Press Here To Start', 'command': _go}) |
| start.pack() |
| endit = Button(mainWidget, |
| {'text': 'Exit', |
| 'command': 'exit', |
| Pack: {'fill' : 'both'}}) |
| mainWidget.mainloop() |
| |
| if __name__ == '__main__': |
| _test() |