1"""A simple but flexible modal dialog box.""" 2 3 4from Tkinter import * 5 6 7class SimpleDialog: 8 9 def __init__(self, master, 10 text='', buttons=[], default=None, cancel=None, 11 title=None, class_=None): 12 if class_: 13 self.root = Toplevel(master, class_=class_) 14 else: 15 self.root = Toplevel(master) 16 if title: 17 self.root.title(title) 18 self.root.iconname(title) 19 self.message = Message(self.root, text=text, aspect=400) 20 self.message.pack(expand=1, fill=BOTH) 21 self.frame = Frame(self.root) 22 self.frame.pack() 23 self.num = default 24 self.cancel = cancel 25 self.default = default 26 self.root.bind('<Return>', self.return_event) 27 for num in range(len(buttons)): 28 s = buttons[num] 29 b = Button(self.frame, text=s, 30 command=(lambda self=self, num=num: self.done(num))) 31 if num == default: 32 b.config(relief=RIDGE, borderwidth=8) 33 b.pack(side=LEFT, fill=BOTH, expand=1) 34 self.root.protocol('WM_DELETE_WINDOW', self.wm_delete_window) 35 self._set_transient(master) 36 37 def _set_transient(self, master, relx=0.5, rely=0.3): 38 widget = self.root 39 widget.withdraw() # Remain invisible while we figure out the geometry 40 widget.transient(master) 41 widget.update_idletasks() # Actualize geometry information 42 if master.winfo_ismapped(): 43 m_width = master.winfo_width() 44 m_height = master.winfo_height() 45 m_x = master.winfo_rootx() 46 m_y = master.winfo_rooty() 47 else: 48 m_width = master.winfo_screenwidth() 49 m_height = master.winfo_screenheight() 50 m_x = m_y = 0 51 w_width = widget.winfo_reqwidth() 52 w_height = widget.winfo_reqheight() 53 x = m_x + (m_width - w_width) * relx 54 y = m_y + (m_height - w_height) * rely 55 if x+w_width > master.winfo_screenwidth(): 56 x = master.winfo_screenwidth() - w_width 57 elif x < 0: 58 x = 0 59 if y+w_height > master.winfo_screenheight(): 60 y = master.winfo_screenheight() - w_height 61 elif y < 0: 62 y = 0 63 widget.geometry("+%d+%d" % (x, y)) 64 widget.deiconify() # Become visible at the desired location 65 66 def go(self): 67 self.root.wait_visibility() 68 self.root.grab_set() 69 self.root.mainloop() 70 self.root.destroy() 71 return self.num 72 73 def return_event(self, event): 74 if self.default is None: 75 self.root.bell() 76 else: 77 self.done(self.default) 78 79 def wm_delete_window(self): 80 if self.cancel is None: 81 self.root.bell() 82 else: 83 self.done(self.cancel) 84 85 def done(self, num): 86 self.num = num 87 self.root.quit() 88 89 90if __name__ == '__main__': 91 92 def test(): 93 root = Tk() 94 def doit(root=root): 95 d = SimpleDialog(root, 96 text="This is a test dialog. " 97 "Would this have been an actual dialog, " 98 "the buttons below would have been glowing " 99 "in soft pink light.\n" 100 "Do you believe this?", 101 buttons=["Yes", "No", "Cancel"], 102 default=0, 103 cancel=2, 104 title="Test Dialog") 105 print d.go() 106 t = Button(root, text='Test', command=doit) 107 t.pack() 108 q = Button(root, text='Quit', command=t.quit) 109 q.pack() 110 t.mainloop() 111 112 test() 113