preview_win_widgets.py
directory : D:\2018_py_proj\TkGridGUI\tkgridgui
Line Count : 489
Line Clip Size : No Clipping
tab_of_notebook_changed Word MatchCase (4) 145 161 181 193
1
2
3 from __future__ import print_function
4 from __future__ import unicode_literals
5
6 from future import standard_library
7 standard_library.install_aliases()
8 from builtins import object
9 """
10 For PreviewWin encapsulate the standard widgets within a Frame
11 since some situations require a compound object (e.g. scrolling)
12
13 Hide widget.config behind widget.pw_config so that widget attributes
14 and compound attributes can be handled properly.
15 """
16
17 import os
18 import sys
19
20 from tkinter import *
21 import tkinter.messagebox
22 from tkinter import Button, Canvas, Checkbutton, Entry, Frame, Label, LabelFrame
23 from tkinter import Listbox, Message, Radiobutton, Spinbox, Text
24 from tkinter import OptionMenu
25 from tkinter.ttk import Combobox, Progressbar, Separator, Treeview, Style, Notebook
26
27 from tkgridgui.edit_options import get_properties_dict, set_attribute_if_possible
28
29 from tkgridgui.grid_notebook import intCast, CONTROL_COLOR_D
30 from tkgridgui.config_file import ConfigInterface
31
32 from tkgridgui.tooltip import CreateToolTip
33
34
35 SCROLL_Y_WIDGETS = set(['Canvas','Listbox','Text','Treeview'])
36 SCROLL_X_WIDGETS = set(['Canvas','Entry','Listbox','Text','Treeview'])
37
38 tkWidgetsD = {'Button':Button, 'Canvas':Canvas, 'Checkbutton':Checkbutton,
39 'Combobox':Combobox, 'Entry':Entry, 'Frame':Frame,
40 'Label':Label, 'LabelFrame':LabelFrame,'Listbox':Listbox, 'Message':Message,
41 'Menubutton':Menubutton, 'Notebook':Notebook ,'OptionMenu':OptionMenu,'Progressbar':Progressbar,
42 'Radiobutton':Radiobutton, 'RadioGroup':LabelFrame,
43 'Scale':Scale, 'Separator':Separator,
44 'Spinbox':Spinbox, 'Text':Text, 'Treeview':Treeview }
45
46
47 class PW_Widget( object ):
48
49 def grid(self, row=0, column=0):
50 self.pw_frame.grid( row=row, column=column )
51
52 def winfo_x(self):
53 return self.pw_frame.winfo_x()
54
55 def winfo_width(self):
56 return self.pw_frame.winfo_width()
57
58 def winfo_y(self):
59 return self.pw_frame.winfo_y()
60
61 def winfo_height(self):
62 return self.pw_frame.winfo_height()
63
64 def destroy(self):
65 self.pw_frame.destroy()
66
67 def destroy_children(self):
68 for child in self.pw_frame.winfo_children():
69 child.destroy()
70
71 def keys(self):
72 """Only get native_widget.keys()"""
73 return list(self.native_widget.keys())
74
75 def cget(self, name):
76 return self.native_widget.cget( name )
77
78 def __getitem__(self, attr_name):
79 """expected attr_name values: relief, background, fg, font, etc."""
80 if attr_name in self.cobj.user_tkOptionD:
81 return self.cobj.user_tkOptionD[ attr_name ]
82
83 if attr_name in self.cobj.default_tkOptionD:
84 return self.cobj.default_tkOptionD[ attr_name ]
85 return None
86
87 def __setitem__(self, key, value):
88
89 if value is None:
90 value = ''
91
92 if value:
93 self.cobj.user_tkOptionD[ key ] = value
94
95 elif key in self.cobj.user_tkOptionD:
96
97 del self.cobj.user_tkOptionD[ key ]
98
99
100
101
102 self.set_native_widget_attr()
103
104
105
106 def __init__(self, disp_frame, cobj):
107 """
108 disp_frame is PreviewWin.prevFrame for Main objects
109 disp_frame is the native_widget of pw_widget's parent otherwise
110
111 cobj is target_tk_app_def.Component (e.g. cobj.widget_type, cobj.widget_name,
112 cobj.row, cobj.col, cobj.tab_label, cobj.tkvar, cobj.user_tkOptionD
113 """
114 self.disp_frame = disp_frame
115 self.cobj = cobj
116
117 self.pw_frame = Frame( disp_frame )
118 self.pw_frame_background = self.pw_frame['background']
119 self.pw_frame_borderwidth = self.pw_frame['borderwidth']
120 self.pw_frame_highlightbackground = self.pw_frame['highlightbackground']
121
122
123
124
125
126
127
128 self.pw_frame.rowconfigure(0, weight=1)
129 self.pw_frame.columnconfigure(0, weight=1)
130
131
132 self.put_native_widget_into_pw_frame()
133
134 def native_widget_clicked(self, event):
135 """When native_widget is clicked, try to change grid_notebook tab."""
136
137 if self.cobj.target_app.grid_notebook is None:
138
139 return
140
141 nb_obj = self.cobj.target_app.grid_notebook
142 nb_obj.set_current_tab_by_label( self.cobj.tab_label )
143
144
145 def tab_of_notebook_changed(self, event):
146 """When PreviewWin Tab changes, try to change grid_notebook tab."""
147
148 if self.cobj.target_app.grid_notebook is None:
149
150 return
151
152 nb = self.native_widget
153 text = nb.tab(nb.select(), "text")
154 nb_obj = self.cobj.target_app.grid_notebook
155
156 for itab, (row, col, tab_name, tab_label) in enumerate( self.cobj.tab_nameL ):
157
158 if text == tab_label:
159 nb_obj.set_current_tab_by_label( tab_name )
160
161
162 break
163
164 def tab_of_notebook_clicked(self, event):
165
166 if self.cobj.target_app.grid_notebook is None:
167
168 return
169
170
171
172
173 nb = self.native_widget
174
175 clicked_tab = nb.tk.call(nb._w, "identify", "tab", event.x, event.y)
176
177
178 active_tab = nb.index(nb.select())
179
180
181 self.tab_of_notebook_changed( event )
182
183
184
185
186 def put_native_widget_into_pw_frame(self):
187
188 cobj = self.cobj
189
190 if cobj.widget_type == 'Notebook':
191
192 self.native_widget = Notebook( self.pw_frame, width=400, height=300 )
193
194 self.native_widget.bind("<ButtonRelease-1>", self.tab_of_notebook_clicked)
195
196 tab_label_str = cobj.user_tkOptionD.get('tab_labels', 'Pine\nBirch\nCherry')
197 tab_labelL = tab_label_str.split('\n')
198
199
200
201
202
203 self.tab_frameL = []
204
205
206 for tab_str in tab_labelL:
207 tab_frame = Frame( self.native_widget )
208 self.native_widget.add( tab_frame, text=tab_str )
209
210
211 self.tab_frameL.append( tab_frame )
212
213 elif cobj.widget_type == 'Frame':
214 self.native_widget = Frame( self.pw_frame, bd=2, relief=GROOVE )
215
216 elif cobj.widget_type == 'Spinbox':
217 self.native_widget = Spinbox(self.pw_frame, from_=0, to=100)
218
219 elif cobj.widget_type == 'Treeview':
220 self.native_widget = Treeview( self.pw_frame )
221 tree = self.native_widget
222
223 tree.insert('', 'end', 'widgets', text='Widget Tour')
224
225
226 tree.insert('', 0, 'gallery', text=cobj.widget_name)
227
228
229 id = tree.insert('', 'end', text='Tutorial')
230
231
232 for tree_widget in sorted( tkWidgetsD.keys() ):
233 tree.insert('widgets', 'end', text=tree_widget)
234 tree.insert(id, 'end', text='Tree')
235
236 elif cobj.widget_type in ['RadioGroup', 'LabelFrame']:
237 self.native_widget = LabelFrame( self.pw_frame, text=cobj.widget_name )
238
239 elif cobj.widget_type == "Canvas":
240 self.native_widget = Canvas( self.pw_frame )
241 w = int(cobj.user_tkOptionD['width'])
242 h = int(cobj.user_tkOptionD['height'])
243
244 self.native_widget.config(bg='#aaffaa')
245 self.native_widget.create_text(w//2,h//2, text=cobj.widget_name,
246 fill="black", width=w, anchor='center')
247
248 elif cobj.tkvar is None:
249
250 self.native_widget = tkWidgetsD[cobj.widget_type]( self.pw_frame )
251
252
253 else:
254
255 if cobj.widget_type == 'Entry':
256 self.native_widget = Entry(self.pw_frame, textvariable=cobj.tkvar)
257
258 elif cobj.widget_type == 'OptionMenu':
259 self.native_widget = OptionMenu(self.pw_frame, cobj.tkvar, "one", "two", "three", "four")
260 cobj.tkvar.set( "two" )
261
262 elif cobj.widget_type == 'Combobox':
263 self.native_widget = Combobox(self.pw_frame, textvariable=cobj.tkvar)
264 self.native_widget['values'] = ('X', 'Y', 'Z')
265 self.native_widget.current(0)
266
267 elif cobj.widget_type == 'Checkbutton':
268 self.native_widget = Checkbutton(self.pw_frame, variable=cobj.tkvar, onvalue="yes", offvalue="no")
269 cobj.tkvar.set("yes")
270
271 elif cobj.widget_type == 'Menubutton':
272 self.native_widget = Menubutton(self.pw_frame, text=cobj.widget_name, relief=GROOVE)
273 self.native_widget.menu = Menu ( self.native_widget , tearoff = 0 )
274 self.native_widget["menu"] = self.native_widget.menu
275 for i,tkvar in enumerate(cobj.tkvar_list):
276 self.native_widget.menu.add_checkbutton(label="option %i"%(i+1,), variable=tkvar )
277
278 elif cobj.widget_type == 'Radiobutton':
279
280 if cobj.tab_label.startswith("RadioGroup"):
281 tkvar = cobj.target_app.compObjD[ cobj.tab_label ].tkvar
282 self.native_widget = Radiobutton(self.pw_frame, variable=tkvar, value=cobj.widget_name)
283
284 self.native_widget.select()
285 else:
286 self.native_widget = Radiobutton(self.pw_frame, variable=cobj.tkvar, value=cobj.widget_name)
287
288
289
290 elif cobj.widget_type == 'Scale':
291 self.native_widget = Scale(self.pw_frame, variable=cobj.tkvar, from_=0, to=100)
292
293 else:
294 print("WARNING... ignoring tk variable for ", cobj.widget_name)
295 self.native_widget = tkWidgetsD[cobj.widget_type]( self.pw_frame )
296
297 self.has_y_scroll = False
298 self.has_x_scroll = False
299 self.vbar = False
300 self.hbar = False
301
302 if cobj.widget_type in ('Treeview',):
303 self.tooltip = CreateToolTip(self.pw_frame, text=cobj.widget_name,
304 background=CONTROL_COLOR_D[ cobj.widget_type ] )
305 else:
306 self.tooltip = CreateToolTip(self.native_widget, text=cobj.widget_name,
307 background=CONTROL_COLOR_D[ cobj.widget_type ] )
308
309
310 self.native_widget.grid(row=0, column=0)
311
312 cobj.default_tkOptionD = get_properties_dict( self.native_widget )
313
314 self.set_native_widget_attr()
315
316
317 if cobj.widget_type != 'Notebook':
318 self.native_widget.bind("<ButtonRelease-1>", self.native_widget_clicked)
319
320
321 def maybe_add_y_scroll(self):
322 if self.has_y_scroll:
323 return
324 else:
325 self.has_y_scroll = True
326 if self.cobj.widget_type == 'Canvas':
327 w = int(self.cobj.user_tkOptionD['width'])
328 h = int(self.cobj.user_tkOptionD['height'])
329 self.native_widget.config( scrollregion=(0,0,w,h*2) )
330
331 vbar=Scrollbar(self.pw_frame,orient=VERTICAL)
332 vbar.grid(row=0, column=1, sticky='ns')
333 vbar.config(command=self.native_widget.yview)
334
335 self.native_widget.config( yscrollcommand=vbar.set )
336 self.vbar = vbar
337
338 def maybe_add_x_scroll(self):
339 if self.has_x_scroll:
340 return
341 else:
342 self.has_x_scroll = True
343 if self.cobj.widget_type == 'Canvas':
344 w = int(self.cobj.user_tkOptionD['width'])
345 h = int(self.cobj.user_tkOptionD['height'])
346 if self.has_y_scroll:
347 self.native_widget.config( scrollregion=(0,0,w*2,h*2) )
348 else:
349 self.native_widget.config( scrollregion=(0,0,w*2,h) )
350
351 elif self.cobj.widget_type == 'Text':
352 self.native_widget.config( wrap=NONE )
353
354 hbar=Scrollbar(self.pw_frame,orient=HORIZONTAL)
355 hbar.grid(row=1, column=0, sticky='ew', columnspan=2)
356 hbar.config(command=self.native_widget.xview)
357
358 self.native_widget.config( xscrollcommand=hbar.set )
359 self.hbar = hbar
360
361
362 def pw_highlight_widget(self):
363 if self['background']:
364 self.native_widget["background"] = "#FF6666"
365 else:
366 self.pw_frame["background"] = "#FF6666"
367 self.pw_frame["highlightbackground"] = "#FF6666"
368 self.pw_frame["borderwidth"] = 5
369
370
371
372 def pw_unhighlight_widget(self):
373 if self['background']:
374 self.native_widget["background"] = self['background']
375 else:
376 self.pw_frame["background"] = self.pw_frame_background
377 self.pw_frame["highlightbackground"] = self.pw_frame_highlightbackground
378 self.pw_frame["borderwidth"] = self.pw_frame_borderwidth
379
380 def handle_scroll_logic(self):
381
382 must_rebuild = False
383
384 if self.cobj.user_tkOptionD.get('scrolly','no') == 'yes':
385 self.maybe_add_y_scroll()
386 elif self.has_y_scroll:
387 must_rebuild = True
388
389 if self.cobj.user_tkOptionD.get('scrollx','no') == 'yes':
390 self.maybe_add_x_scroll()
391 elif self.has_x_scroll:
392 must_rebuild = True
393
394 if must_rebuild:
395 self.destroy_children()
396 self.put_native_widget_into_pw_frame()
397
398 def set_native_widget_attr(self):
399
400
401
402
403 self.handle_scroll_logic()
404
405 for key, val in list(self.cobj.user_tkOptionD.items()):
406 if key == 'sticky':
407
408 set_attribute_if_possible(self.pw_frame, key, val)
409 set_attribute_if_possible(self.native_widget, key, val)
410
411 elif key in PW_FRAME_ATTR:
412 set_attribute_if_possible(self.pw_frame, key, val)
413 else:
414 set_attribute_if_possible(self.native_widget, key, val)
415
416
417 PW_FRAME_ATTR = ['rowspan','columnspan','sticky']
418
419
420 if __name__=="__main__":
421
422 from tkgridgui.preview_win import PreviewWin
423 from tkgridgui.target_tk_app_def import Component
424
425
426 widgetL = sorted( tkWidgetsD.keys() )
427 def get_widget_type_name( i ):
428 wtype = widgetL[ i % len(widgetL) ]
429 i,r = divmod( i, len(widgetL) )
430 name = wtype + '_%i'%(i+1, )
431 return wtype, name
432
433 class TestPW(object):
434 def __init__(self, master):
435 frame = Frame(master, width=300, height=300)
436 frame.pack()
437 self.master = master
438 self.x, self.y, self.w, self.h = -1,-1,-1,-1
439
440 self.Button_1 = Button(text="Test PW_Widget", relief="raised", width="15")
441 self.Button_1.place(x=84, y=36)
442 self.Button_1.bind("<ButtonRelease-1>", self.Button_1_Click)
443
444 self.PreviewWin = None
445 self.num_comp = 0
446
447 def cleanupOnQuit(self):
448
449 self.PreviewWin.destroy()
450 self.master.allow_subWindows_to_close = 1
451 self.master.destroy()
452
453
454 def Button_1_Click(self, event):
455
456 if self.PreviewWin is None:
457 self.PreviewWin = PreviewWin( self.master )
458 else:
459 wtype, name = get_widget_type_name( self.num_comp )
460 col,row = divmod( self.num_comp, 9 )
461
462
463 c = Component( widget_type=wtype,
464 widget_name=name,
465 tab_label='Main',
466 row=row, col=col, target_app=self )
467 self.num_comp += 1
468
469 if wtype in SCROLL_Y_WIDGETS:
470 c.user_tkOptionD['scrolly'] = 'yes'
471 if wtype in SCROLL_X_WIDGETS:
472 c.user_tkOptionD['scrollx'] = 'yes'
473
474
475 pw = PW_Widget( self.PreviewWin.prevFrame, c )
476 self.PreviewWin.add_widget( c.row, c.col, pw )
477
478
479
480 root = Tk()
481 MainWin = root
482 MainWin.title('Main Window')
483
484 MainWin.config(background='#FFFACD')
485
486 grid_gui = TestPW( MainWin )
487
488 MainWin.mainloop()
489