|
1 """A simple but flexible modal dialog box.""" |
|
2 |
|
3 |
|
4 from Tkinter import * |
|
5 |
|
6 |
|
7 class 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 |
|
90 if __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() |