blob: 6198c4c949218f28ba0586341ef8a661c5319fe9 [file] [log] [blame]
Georg Brandl33cece02008-05-20 06:58:21 +00001"""Wrapper functions for Tcl/Tk.
2
3Tkinter provides classes which allow the display, positioning and
4control of widgets. Toplevel widgets are Tk and Toplevel. Other
5widgets are Frame, Label, Entry, Text, Canvas, Button, Radiobutton,
6Checkbutton, Scale, Listbox, Scrollbar, OptionMenu, Spinbox
7LabelFrame and PanedWindow.
8
9Properties of the widgets are specified with keyword arguments.
10Keyword arguments have the same name as the corresponding resource
11under Tk.
12
13Widgets are positioned with one of the geometry managers Place, Pack
14or Grid. These managers can be called with methods place, pack, grid
15available in every Widget.
16
17Actions are bound to events by resources (e.g. keyword argument
18command) or with the method bind.
19
20Example (Hello, World):
Georg Brandl6634bf22008-05-20 07:13:37 +000021import Tkinter
22from Tkconstants import *
23tk = Tkinter.Tk()
24frame = Tkinter.Frame(tk, relief=RIDGE, borderwidth=2)
Georg Brandl33cece02008-05-20 06:58:21 +000025frame.pack(fill=BOTH,expand=1)
Georg Brandl6634bf22008-05-20 07:13:37 +000026label = Tkinter.Label(frame, text="Hello, World")
Georg Brandl33cece02008-05-20 06:58:21 +000027label.pack(fill=X, expand=1)
Georg Brandl6634bf22008-05-20 07:13:37 +000028button = Tkinter.Button(frame,text="Exit",command=tk.destroy)
Georg Brandl33cece02008-05-20 06:58:21 +000029button.pack(side=BOTTOM)
30tk.mainloop()
31"""
32
Senthil Kumaran4af1c6a2011-07-28 22:30:27 +080033__version__ = "$Revision: 81008 $"
Georg Brandl33cece02008-05-20 06:58:21 +000034
35import sys
36if sys.platform == "win32":
37 # Attempt to configure Tcl/Tk without requiring PATH
Georg Brandl6634bf22008-05-20 07:13:37 +000038 import FixTk
Georg Brandl33cece02008-05-20 06:58:21 +000039import _tkinter # If this fails your Python may not be configured for Tk
Georg Brandl6634bf22008-05-20 07:13:37 +000040tkinter = _tkinter # b/w compat for export
Georg Brandl33cece02008-05-20 06:58:21 +000041TclError = _tkinter.TclError
42from types import *
Georg Brandl6634bf22008-05-20 07:13:37 +000043from Tkconstants import *
Serhiy Storchakae39ba042013-01-15 18:01:21 +020044import re
Georg Brandl33cece02008-05-20 06:58:21 +000045
46wantobjects = 1
47
48TkVersion = float(_tkinter.TK_VERSION)
49TclVersion = float(_tkinter.TCL_VERSION)
50
51READABLE = _tkinter.READABLE
52WRITABLE = _tkinter.WRITABLE
53EXCEPTION = _tkinter.EXCEPTION
54
55# These are not always defined, e.g. not on Win32 with Tk 8.0 :-(
56try: _tkinter.createfilehandler
57except AttributeError: _tkinter.createfilehandler = None
58try: _tkinter.deletefilehandler
59except AttributeError: _tkinter.deletefilehandler = None
60
61
Serhiy Storchakae39ba042013-01-15 18:01:21 +020062_magic_re = re.compile(r'([\\{}])')
63_space_re = re.compile(r'([\s])')
64
65def _join(value):
66 """Internal function."""
67 return ' '.join(map(_stringify, value))
68
69def _stringify(value):
70 """Internal function."""
71 if isinstance(value, (list, tuple)):
72 if len(value) == 1:
73 value = _stringify(value[0])
74 if value[0] == '{':
75 value = '{%s}' % value
76 else:
77 value = '{%s}' % _join(value)
78 else:
Serhiy Storchaka9be238d2014-01-07 19:32:58 +020079 if isinstance(value, str):
80 value = unicode(value, 'utf-8')
81 elif not isinstance(value, unicode):
Serhiy Storchakae39ba042013-01-15 18:01:21 +020082 value = str(value)
83 if not value:
84 value = '{}'
85 elif _magic_re.search(value):
86 # add '\' before special characters and spaces
87 value = _magic_re.sub(r'\\\1', value)
88 value = _space_re.sub(r'\\\1', value)
89 elif value[0] == '"' or _space_re.search(value):
90 value = '{%s}' % value
91 return value
92
Georg Brandl33cece02008-05-20 06:58:21 +000093def _flatten(tuple):
94 """Internal function."""
95 res = ()
96 for item in tuple:
97 if type(item) in (TupleType, ListType):
98 res = res + _flatten(item)
99 elif item is not None:
100 res = res + (item,)
101 return res
102
103try: _flatten = _tkinter._flatten
104except AttributeError: pass
105
106def _cnfmerge(cnfs):
107 """Internal function."""
108 if type(cnfs) is DictionaryType:
109 return cnfs
110 elif type(cnfs) in (NoneType, StringType):
111 return cnfs
112 else:
113 cnf = {}
114 for c in _flatten(cnfs):
115 try:
116 cnf.update(c)
117 except (AttributeError, TypeError), msg:
118 print "_cnfmerge: fallback due to:", msg
119 for k, v in c.items():
120 cnf[k] = v
121 return cnf
122
123try: _cnfmerge = _tkinter._cnfmerge
124except AttributeError: pass
125
Serhiy Storchakaceaf6822014-09-06 22:47:02 +0300126def _splitdict(tk, v, cut_minus=True, conv=None):
127 """Return a properly formatted dict built from Tcl list pairs.
128
129 If cut_minus is True, the supposed '-' prefix will be removed from
130 keys. If conv is specified, it is used to convert values.
131
132 Tcl list is expected to contain an even number of elements.
133 """
134 t = tk.splitlist(v)
135 if len(t) % 2:
136 raise RuntimeError('Tcl list representing a dict is expected '
137 'to contain an even number of elements')
138 it = iter(t)
139 dict = {}
140 for key, value in zip(it, it):
141 key = str(key)
142 if cut_minus and key[0] == '-':
143 key = key[1:]
144 if conv:
145 value = conv(value)
146 dict[key] = value
147 return dict
148
Georg Brandl33cece02008-05-20 06:58:21 +0000149class Event:
150 """Container for the properties of an event.
151
152 Instances of this type are generated if one of the following events occurs:
153
154 KeyPress, KeyRelease - for keyboard events
155 ButtonPress, ButtonRelease, Motion, Enter, Leave, MouseWheel - for mouse events
156 Visibility, Unmap, Map, Expose, FocusIn, FocusOut, Circulate,
157 Colormap, Gravity, Reparent, Property, Destroy, Activate,
158 Deactivate - for window events.
159
160 If a callback function for one of these events is registered
161 using bind, bind_all, bind_class, or tag_bind, the callback is
162 called with an Event as first argument. It will have the
163 following attributes (in braces are the event types for which
164 the attribute is valid):
165
166 serial - serial number of event
167 num - mouse button pressed (ButtonPress, ButtonRelease)
168 focus - whether the window has the focus (Enter, Leave)
169 height - height of the exposed window (Configure, Expose)
170 width - width of the exposed window (Configure, Expose)
171 keycode - keycode of the pressed key (KeyPress, KeyRelease)
172 state - state of the event as a number (ButtonPress, ButtonRelease,
173 Enter, KeyPress, KeyRelease,
174 Leave, Motion)
175 state - state as a string (Visibility)
176 time - when the event occurred
177 x - x-position of the mouse
178 y - y-position of the mouse
179 x_root - x-position of the mouse on the screen
180 (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion)
181 y_root - y-position of the mouse on the screen
182 (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion)
183 char - pressed character (KeyPress, KeyRelease)
184 send_event - see X/Windows documentation
185 keysym - keysym of the event as a string (KeyPress, KeyRelease)
186 keysym_num - keysym of the event as a number (KeyPress, KeyRelease)
187 type - type of the event as a number
188 widget - widget in which the event occurred
189 delta - delta of wheel movement (MouseWheel)
190 """
191 pass
192
193_support_default_root = 1
194_default_root = None
195
196def NoDefaultRoot():
197 """Inhibit setting of default root window.
198
199 Call this function to inhibit that the first instance of
200 Tk is used for windows without an explicit parent window.
201 """
202 global _support_default_root
203 _support_default_root = 0
204 global _default_root
205 _default_root = None
206 del _default_root
207
208def _tkerror(err):
209 """Internal function."""
210 pass
211
Andrew Svetlov33b9b712012-12-10 00:05:08 +0200212def _exit(code=0):
Andrew Svetlov4bb142b2012-12-18 21:27:37 +0200213 """Internal function. Calling it will raise the exception SystemExit."""
Andrew Svetlov33b9b712012-12-10 00:05:08 +0200214 try:
215 code = int(code)
216 except ValueError:
217 pass
Georg Brandl33cece02008-05-20 06:58:21 +0000218 raise SystemExit, code
219
220_varnum = 0
221class Variable:
222 """Class to define value holders for e.g. buttons.
223
224 Subclasses StringVar, IntVar, DoubleVar, BooleanVar are specializations
225 that constrain the type of the value returned from get()."""
226 _default = ""
Serhiy Storchaka44ae5132014-08-17 15:31:41 +0300227 _tclCommands = None
Georg Brandl33cece02008-05-20 06:58:21 +0000228 def __init__(self, master=None, value=None, name=None):
229 """Construct a variable
230
231 MASTER can be given as master widget.
232 VALUE is an optional value (defaults to "")
233 NAME is an optional Tcl name (defaults to PY_VARnum).
234
235 If NAME matches an existing variable and VALUE is omitted
236 then the existing value is retained.
237 """
238 global _varnum
239 if not master:
240 master = _default_root
Serhiy Storchaka44ae5132014-08-17 15:31:41 +0300241 self._root = master._root()
Georg Brandl33cece02008-05-20 06:58:21 +0000242 self._tk = master.tk
243 if name:
244 self._name = name
245 else:
246 self._name = 'PY_VAR' + repr(_varnum)
247 _varnum += 1
248 if value is not None:
249 self.set(value)
Serhiy Storchaka5e116552013-12-26 20:05:53 +0200250 elif not self._tk.getboolean(self._tk.call("info", "exists", self._name)):
Georg Brandl33cece02008-05-20 06:58:21 +0000251 self.set(self._default)
252 def __del__(self):
253 """Unset the variable in Tcl."""
Serhiy Storchaka44ae5132014-08-17 15:31:41 +0300254 if self._tk is None:
255 return
256 if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
Serhiy Storchaka5e116552013-12-26 20:05:53 +0200257 self._tk.globalunsetvar(self._name)
Serhiy Storchaka44ae5132014-08-17 15:31:41 +0300258 if self._tclCommands is not None:
259 for name in self._tclCommands:
260 #print '- Tkinter: deleted command', name
261 self._tk.deletecommand(name)
262 self._tclCommands = None
Georg Brandl33cece02008-05-20 06:58:21 +0000263 def __str__(self):
264 """Return the name of the variable in Tcl."""
265 return self._name
266 def set(self, value):
267 """Set the variable to VALUE."""
268 return self._tk.globalsetvar(self._name, value)
269 def get(self):
270 """Return value of variable."""
271 return self._tk.globalgetvar(self._name)
272 def trace_variable(self, mode, callback):
273 """Define a trace callback for the variable.
274
275 MODE is one of "r", "w", "u" for read, write, undefine.
276 CALLBACK must be a function which is called when
277 the variable is read, written or undefined.
278
279 Return the name of the callback.
280 """
Serhiy Storchaka44ae5132014-08-17 15:31:41 +0300281 f = CallWrapper(callback, None, self._root).__call__
282 cbname = repr(id(f))
283 try:
284 callback = callback.im_func
285 except AttributeError:
286 pass
287 try:
288 cbname = cbname + callback.__name__
289 except AttributeError:
290 pass
291 self._tk.createcommand(cbname, f)
292 if self._tclCommands is None:
293 self._tclCommands = []
294 self._tclCommands.append(cbname)
Georg Brandl33cece02008-05-20 06:58:21 +0000295 self._tk.call("trace", "variable", self._name, mode, cbname)
296 return cbname
297 trace = trace_variable
298 def trace_vdelete(self, mode, cbname):
299 """Delete the trace callback for a variable.
300
301 MODE is one of "r", "w", "u" for read, write, undefine.
302 CBNAME is the name of the callback returned from trace_variable or trace.
303 """
304 self._tk.call("trace", "vdelete", self._name, mode, cbname)
Serhiy Storchaka199b7d52016-06-26 17:41:14 +0300305 cbname = self._tk.splitlist(cbname)[0]
306 for m, ca in self.trace_vinfo():
307 if self._tk.splitlist(ca)[0] == cbname:
308 break
309 else:
310 self._tk.deletecommand(cbname)
311 try:
312 self._tclCommands.remove(cbname)
313 except ValueError:
314 pass
Georg Brandl33cece02008-05-20 06:58:21 +0000315 def trace_vinfo(self):
316 """Return all trace callback information."""
Serhiy Storchaka199b7d52016-06-26 17:41:14 +0300317 return map(self._tk.splitlist, self._tk.splitlist(
Georg Brandl33cece02008-05-20 06:58:21 +0000318 self._tk.call("trace", "vinfo", self._name)))
319 def __eq__(self, other):
320 """Comparison for equality (==).
321
322 Note: if the Variable's master matters to behavior
323 also compare self._master == other._master
324 """
325 return self.__class__.__name__ == other.__class__.__name__ \
326 and self._name == other._name
327
328class StringVar(Variable):
329 """Value holder for strings variables."""
330 _default = ""
331 def __init__(self, master=None, value=None, name=None):
332 """Construct a string variable.
333
334 MASTER can be given as master widget.
335 VALUE is an optional value (defaults to "")
336 NAME is an optional Tcl name (defaults to PY_VARnum).
337
338 If NAME matches an existing variable and VALUE is omitted
339 then the existing value is retained.
340 """
341 Variable.__init__(self, master, value, name)
342
343 def get(self):
344 """Return value of variable as string."""
345 value = self._tk.globalgetvar(self._name)
346 if isinstance(value, basestring):
347 return value
348 return str(value)
349
350class IntVar(Variable):
351 """Value holder for integer variables."""
352 _default = 0
353 def __init__(self, master=None, value=None, name=None):
354 """Construct an integer variable.
355
356 MASTER can be given as master widget.
357 VALUE is an optional value (defaults to 0)
358 NAME is an optional Tcl name (defaults to PY_VARnum).
359
360 If NAME matches an existing variable and VALUE is omitted
361 then the existing value is retained.
362 """
363 Variable.__init__(self, master, value, name)
364
365 def set(self, value):
366 """Set the variable to value, converting booleans to integers."""
367 if isinstance(value, bool):
368 value = int(value)
369 return Variable.set(self, value)
370
371 def get(self):
372 """Return the value of the variable as an integer."""
373 return getint(self._tk.globalgetvar(self._name))
374
375class DoubleVar(Variable):
376 """Value holder for float variables."""
377 _default = 0.0
378 def __init__(self, master=None, value=None, name=None):
379 """Construct a float variable.
380
381 MASTER can be given as master widget.
382 VALUE is an optional value (defaults to 0.0)
383 NAME is an optional Tcl name (defaults to PY_VARnum).
384
385 If NAME matches an existing variable and VALUE is omitted
386 then the existing value is retained.
387 """
388 Variable.__init__(self, master, value, name)
389
390 def get(self):
391 """Return the value of the variable as a float."""
392 return getdouble(self._tk.globalgetvar(self._name))
393
394class BooleanVar(Variable):
395 """Value holder for boolean variables."""
396 _default = False
397 def __init__(self, master=None, value=None, name=None):
398 """Construct a boolean variable.
399
400 MASTER can be given as master widget.
401 VALUE is an optional value (defaults to False)
402 NAME is an optional Tcl name (defaults to PY_VARnum).
403
404 If NAME matches an existing variable and VALUE is omitted
405 then the existing value is retained.
406 """
407 Variable.__init__(self, master, value, name)
408
Serhiy Storchakaf29bc702015-04-04 12:42:25 +0300409 def set(self, value):
410 """Set the variable to VALUE."""
411 return self._tk.globalsetvar(self._name, self._tk.getboolean(value))
412
Georg Brandl33cece02008-05-20 06:58:21 +0000413 def get(self):
414 """Return the value of the variable as a bool."""
415 return self._tk.getboolean(self._tk.globalgetvar(self._name))
416
417def mainloop(n=0):
418 """Run the main loop of Tcl."""
419 _default_root.tk.mainloop(n)
420
421getint = int
422
423getdouble = float
424
425def getboolean(s):
426 """Convert true and false to integer values 1 and 0."""
427 return _default_root.tk.getboolean(s)
428
429# Methods defined on both toplevel and interior widgets
430class Misc:
431 """Internal class.
432
433 Base class which defines methods common for interior widgets."""
434
435 # XXX font command?
436 _tclCommands = None
437 def destroy(self):
438 """Internal function.
439
440 Delete all Tcl commands created for
441 this widget in the Tcl interpreter."""
442 if self._tclCommands is not None:
443 for name in self._tclCommands:
444 #print '- Tkinter: deleted command', name
445 self.tk.deletecommand(name)
446 self._tclCommands = None
447 def deletecommand(self, name):
448 """Internal function.
449
450 Delete the Tcl command provided in NAME."""
451 #print '- Tkinter: deleted command', name
452 self.tk.deletecommand(name)
453 try:
454 self._tclCommands.remove(name)
455 except ValueError:
456 pass
457 def tk_strictMotif(self, boolean=None):
458 """Set Tcl internal variable, whether the look and feel
459 should adhere to Motif.
460
461 A parameter of 1 means adhere to Motif (e.g. no color
462 change if mouse passes over slider).
463 Returns the set value."""
464 return self.tk.getboolean(self.tk.call(
465 'set', 'tk_strictMotif', boolean))
466 def tk_bisque(self):
467 """Change the color scheme to light brown as used in Tk 3.6 and before."""
468 self.tk.call('tk_bisque')
469 def tk_setPalette(self, *args, **kw):
470 """Set a new color scheme for all widget elements.
471
472 A single color as argument will cause that all colors of Tk
473 widget elements are derived from this.
474 Alternatively several keyword parameters and its associated
475 colors can be given. The following keywords are valid:
476 activeBackground, foreground, selectColor,
477 activeForeground, highlightBackground, selectBackground,
478 background, highlightColor, selectForeground,
479 disabledForeground, insertBackground, troughColor."""
480 self.tk.call(('tk_setPalette',)
481 + _flatten(args) + _flatten(kw.items()))
482 def tk_menuBar(self, *args):
483 """Do not use. Needed in Tk 3.6 and earlier."""
Serhiy Storchaka2ce9ddd2014-07-25 12:23:08 +0300484 # obsolete since Tk 4.0
485 import warnings
486 warnings.warn('tk_menuBar() does nothing and will be removed in 3.6',
487 DeprecationWarning, stacklevel=2)
Georg Brandl33cece02008-05-20 06:58:21 +0000488 def wait_variable(self, name='PY_VAR'):
489 """Wait until the variable is modified.
490
491 A parameter of type IntVar, StringVar, DoubleVar or
492 BooleanVar must be given."""
493 self.tk.call('tkwait', 'variable', name)
494 waitvar = wait_variable # XXX b/w compat
495 def wait_window(self, window=None):
496 """Wait until a WIDGET is destroyed.
497
498 If no parameter is given self is used."""
499 if window is None:
500 window = self
501 self.tk.call('tkwait', 'window', window._w)
502 def wait_visibility(self, window=None):
503 """Wait until the visibility of a WIDGET changes
504 (e.g. it appears).
505
506 If no parameter is given self is used."""
507 if window is None:
508 window = self
509 self.tk.call('tkwait', 'visibility', window._w)
510 def setvar(self, name='PY_VAR', value='1'):
511 """Set Tcl variable NAME to VALUE."""
512 self.tk.setvar(name, value)
513 def getvar(self, name='PY_VAR'):
514 """Return value of Tcl variable NAME."""
515 return self.tk.getvar(name)
516 getint = int
517 getdouble = float
518 def getboolean(self, s):
519 """Return a boolean value for Tcl boolean values true and false given as parameter."""
520 return self.tk.getboolean(s)
521 def focus_set(self):
522 """Direct input focus to this widget.
523
524 If the application currently does not have the focus
525 this widget will get the focus if the application gets
526 the focus through the window manager."""
527 self.tk.call('focus', self._w)
528 focus = focus_set # XXX b/w compat?
529 def focus_force(self):
530 """Direct input focus to this widget even if the
531 application does not have the focus. Use with
532 caution!"""
533 self.tk.call('focus', '-force', self._w)
534 def focus_get(self):
535 """Return the widget which has currently the focus in the
536 application.
537
538 Use focus_displayof to allow working with several
539 displays. Return None if application does not have
540 the focus."""
541 name = self.tk.call('focus')
542 if name == 'none' or not name: return None
543 return self._nametowidget(name)
544 def focus_displayof(self):
545 """Return the widget which has currently the focus on the
546 display where this widget is located.
547
548 Return None if the application does not have the focus."""
549 name = self.tk.call('focus', '-displayof', self._w)
550 if name == 'none' or not name: return None
551 return self._nametowidget(name)
552 def focus_lastfor(self):
553 """Return the widget which would have the focus if top level
554 for this widget gets the focus from the window manager."""
555 name = self.tk.call('focus', '-lastfor', self._w)
556 if name == 'none' or not name: return None
557 return self._nametowidget(name)
558 def tk_focusFollowsMouse(self):
559 """The widget under mouse will get automatically focus. Can not
560 be disabled easily."""
561 self.tk.call('tk_focusFollowsMouse')
562 def tk_focusNext(self):
563 """Return the next widget in the focus order which follows
564 widget which has currently the focus.
565
566 The focus order first goes to the next child, then to
567 the children of the child recursively and then to the
568 next sibling which is higher in the stacking order. A
569 widget is omitted if it has the takefocus resource set
570 to 0."""
571 name = self.tk.call('tk_focusNext', self._w)
572 if not name: return None
573 return self._nametowidget(name)
574 def tk_focusPrev(self):
575 """Return previous widget in the focus order. See tk_focusNext for details."""
576 name = self.tk.call('tk_focusPrev', self._w)
577 if not name: return None
578 return self._nametowidget(name)
579 def after(self, ms, func=None, *args):
580 """Call function once after given time.
581
582 MS specifies the time in milliseconds. FUNC gives the
583 function which shall be called. Additional parameters
584 are given as parameters to the function call. Return
585 identifier to cancel scheduling with after_cancel."""
586 if not func:
587 # I'd rather use time.sleep(ms*0.001)
588 self.tk.call('after', ms)
589 else:
590 def callit():
591 try:
592 func(*args)
593 finally:
594 try:
595 self.deletecommand(name)
596 except TclError:
597 pass
Serhiy Storchakad3ea0652014-08-24 09:07:09 +0300598 callit.__name__ = func.__name__
Georg Brandl33cece02008-05-20 06:58:21 +0000599 name = self._register(callit)
600 return self.tk.call('after', ms, name)
601 def after_idle(self, func, *args):
602 """Call FUNC once if the Tcl main loop has no event to
603 process.
604
605 Return an identifier to cancel the scheduling with
606 after_cancel."""
607 return self.after('idle', func, *args)
608 def after_cancel(self, id):
609 """Cancel scheduling of function identified with ID.
610
611 Identifier returned by after or after_idle must be
612 given as first parameter."""
613 try:
614 data = self.tk.call('after', 'info', id)
615 # In Tk 8.3, splitlist returns: (script, type)
616 # In Tk 8.4, splitlist may return (script, type) or (script,)
617 script = self.tk.splitlist(data)[0]
618 self.deletecommand(script)
619 except TclError:
620 pass
621 self.tk.call('after', 'cancel', id)
622 def bell(self, displayof=0):
623 """Ring a display's bell."""
624 self.tk.call(('bell',) + self._displayof(displayof))
625
626 # Clipboard handling:
627 def clipboard_get(self, **kw):
628 """Retrieve data from the clipboard on window's display.
629
630 The window keyword defaults to the root window of the Tkinter
631 application.
632
633 The type keyword specifies the form in which the data is
634 to be returned and should be an atom name such as STRING
Ned Deily724a55c2012-05-15 18:05:57 -0700635 or FILE_NAME. Type defaults to STRING, except on X11, where the default
636 is to try UTF8_STRING and fall back to STRING.
Georg Brandl33cece02008-05-20 06:58:21 +0000637
638 This command is equivalent to:
639
640 selection_get(CLIPBOARD)
641 """
Ned Deily724a55c2012-05-15 18:05:57 -0700642 if 'type' not in kw and self._windowingsystem == 'x11':
643 try:
644 kw['type'] = 'UTF8_STRING'
645 return self.tk.call(('clipboard', 'get') + self._options(kw))
646 except TclError:
647 del kw['type']
Georg Brandl33cece02008-05-20 06:58:21 +0000648 return self.tk.call(('clipboard', 'get') + self._options(kw))
649
650 def clipboard_clear(self, **kw):
651 """Clear the data in the Tk clipboard.
652
653 A widget specified for the optional displayof keyword
654 argument specifies the target display."""
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000655 if 'displayof' not in kw: kw['displayof'] = self._w
Georg Brandl33cece02008-05-20 06:58:21 +0000656 self.tk.call(('clipboard', 'clear') + self._options(kw))
657 def clipboard_append(self, string, **kw):
658 """Append STRING to the Tk clipboard.
659
660 A widget specified at the optional displayof keyword
661 argument specifies the target display. The clipboard
662 can be retrieved with selection_get."""
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000663 if 'displayof' not in kw: kw['displayof'] = self._w
Georg Brandl33cece02008-05-20 06:58:21 +0000664 self.tk.call(('clipboard', 'append') + self._options(kw)
665 + ('--', string))
666 # XXX grab current w/o window argument
667 def grab_current(self):
668 """Return widget which has currently the grab in this application
669 or None."""
670 name = self.tk.call('grab', 'current', self._w)
671 if not name: return None
672 return self._nametowidget(name)
673 def grab_release(self):
674 """Release grab for this widget if currently set."""
675 self.tk.call('grab', 'release', self._w)
676 def grab_set(self):
677 """Set grab for this widget.
678
679 A grab directs all events to this and descendant
680 widgets in the application."""
681 self.tk.call('grab', 'set', self._w)
682 def grab_set_global(self):
683 """Set global grab for this widget.
684
685 A global grab directs all events to this and
686 descendant widgets on the display. Use with caution -
687 other applications do not get events anymore."""
688 self.tk.call('grab', 'set', '-global', self._w)
689 def grab_status(self):
690 """Return None, "local" or "global" if this widget has
691 no, a local or a global grab."""
692 status = self.tk.call('grab', 'status', self._w)
693 if status == 'none': status = None
694 return status
695 def option_add(self, pattern, value, priority = None):
696 """Set a VALUE (second parameter) for an option
697 PATTERN (first parameter).
698
699 An optional third parameter gives the numeric priority
700 (defaults to 80)."""
701 self.tk.call('option', 'add', pattern, value, priority)
702 def option_clear(self):
703 """Clear the option database.
704
705 It will be reloaded if option_add is called."""
706 self.tk.call('option', 'clear')
707 def option_get(self, name, className):
708 """Return the value for an option NAME for this widget
709 with CLASSNAME.
710
711 Values with higher priority override lower values."""
712 return self.tk.call('option', 'get', self._w, name, className)
713 def option_readfile(self, fileName, priority = None):
714 """Read file FILENAME into the option database.
715
716 An optional second parameter gives the numeric
717 priority."""
718 self.tk.call('option', 'readfile', fileName, priority)
719 def selection_clear(self, **kw):
720 """Clear the current X selection."""
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000721 if 'displayof' not in kw: kw['displayof'] = self._w
Georg Brandl33cece02008-05-20 06:58:21 +0000722 self.tk.call(('selection', 'clear') + self._options(kw))
723 def selection_get(self, **kw):
724 """Return the contents of the current X selection.
725
726 A keyword parameter selection specifies the name of
727 the selection and defaults to PRIMARY. A keyword
728 parameter displayof specifies a widget on the display
Ned Deily724a55c2012-05-15 18:05:57 -0700729 to use. A keyword parameter type specifies the form of data to be
730 fetched, defaulting to STRING except on X11, where UTF8_STRING is tried
731 before STRING."""
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000732 if 'displayof' not in kw: kw['displayof'] = self._w
Ned Deily724a55c2012-05-15 18:05:57 -0700733 if 'type' not in kw and self._windowingsystem == 'x11':
734 try:
735 kw['type'] = 'UTF8_STRING'
736 return self.tk.call(('selection', 'get') + self._options(kw))
737 except TclError:
738 del kw['type']
Georg Brandl33cece02008-05-20 06:58:21 +0000739 return self.tk.call(('selection', 'get') + self._options(kw))
740 def selection_handle(self, command, **kw):
741 """Specify a function COMMAND to call if the X
742 selection owned by this widget is queried by another
743 application.
744
745 This function must return the contents of the
746 selection. The function will be called with the
747 arguments OFFSET and LENGTH which allows the chunking
748 of very long selections. The following keyword
749 parameters can be provided:
750 selection - name of the selection (default PRIMARY),
751 type - type of the selection (e.g. STRING, FILE_NAME)."""
752 name = self._register(command)
753 self.tk.call(('selection', 'handle') + self._options(kw)
754 + (self._w, name))
755 def selection_own(self, **kw):
756 """Become owner of X selection.
757
758 A keyword parameter selection specifies the name of
759 the selection (default PRIMARY)."""
760 self.tk.call(('selection', 'own') +
761 self._options(kw) + (self._w,))
762 def selection_own_get(self, **kw):
763 """Return owner of X selection.
764
765 The following keyword parameter can
766 be provided:
767 selection - name of the selection (default PRIMARY),
768 type - type of the selection (e.g. STRING, FILE_NAME)."""
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +0000769 if 'displayof' not in kw: kw['displayof'] = self._w
Georg Brandl33cece02008-05-20 06:58:21 +0000770 name = self.tk.call(('selection', 'own') + self._options(kw))
771 if not name: return None
772 return self._nametowidget(name)
773 def send(self, interp, cmd, *args):
774 """Send Tcl command CMD to different interpreter INTERP to be executed."""
775 return self.tk.call(('send', interp, cmd) + args)
776 def lower(self, belowThis=None):
777 """Lower this widget in the stacking order."""
778 self.tk.call('lower', self._w, belowThis)
779 def tkraise(self, aboveThis=None):
780 """Raise this widget in the stacking order."""
781 self.tk.call('raise', self._w, aboveThis)
782 lift = tkraise
783 def colormodel(self, value=None):
784 """Useless. Not implemented in Tk."""
785 return self.tk.call('tk', 'colormodel', self._w, value)
786 def winfo_atom(self, name, displayof=0):
787 """Return integer which represents atom NAME."""
788 args = ('winfo', 'atom') + self._displayof(displayof) + (name,)
789 return getint(self.tk.call(args))
790 def winfo_atomname(self, id, displayof=0):
791 """Return name of atom with identifier ID."""
792 args = ('winfo', 'atomname') \
793 + self._displayof(displayof) + (id,)
794 return self.tk.call(args)
795 def winfo_cells(self):
796 """Return number of cells in the colormap for this widget."""
797 return getint(
798 self.tk.call('winfo', 'cells', self._w))
799 def winfo_children(self):
800 """Return a list of all widgets which are children of this widget."""
801 result = []
802 for child in self.tk.splitlist(
803 self.tk.call('winfo', 'children', self._w)):
804 try:
805 # Tcl sometimes returns extra windows, e.g. for
806 # menus; those need to be skipped
807 result.append(self._nametowidget(child))
808 except KeyError:
809 pass
810 return result
811
812 def winfo_class(self):
813 """Return window class name of this widget."""
814 return self.tk.call('winfo', 'class', self._w)
815 def winfo_colormapfull(self):
816 """Return true if at the last color request the colormap was full."""
817 return self.tk.getboolean(
818 self.tk.call('winfo', 'colormapfull', self._w))
819 def winfo_containing(self, rootX, rootY, displayof=0):
820 """Return the widget which is at the root coordinates ROOTX, ROOTY."""
821 args = ('winfo', 'containing') \
822 + self._displayof(displayof) + (rootX, rootY)
823 name = self.tk.call(args)
824 if not name: return None
825 return self._nametowidget(name)
826 def winfo_depth(self):
827 """Return the number of bits per pixel."""
828 return getint(self.tk.call('winfo', 'depth', self._w))
829 def winfo_exists(self):
830 """Return true if this widget exists."""
831 return getint(
832 self.tk.call('winfo', 'exists', self._w))
833 def winfo_fpixels(self, number):
834 """Return the number of pixels for the given distance NUMBER
835 (e.g. "3c") as float."""
836 return getdouble(self.tk.call(
837 'winfo', 'fpixels', self._w, number))
838 def winfo_geometry(self):
839 """Return geometry string for this widget in the form "widthxheight+X+Y"."""
840 return self.tk.call('winfo', 'geometry', self._w)
841 def winfo_height(self):
842 """Return height of this widget."""
843 return getint(
844 self.tk.call('winfo', 'height', self._w))
845 def winfo_id(self):
846 """Return identifier ID for this widget."""
Victor Stinnerf6d64802017-07-06 10:22:50 +0200847 return int(self.tk.call('winfo', 'id', self._w), 0)
Georg Brandl33cece02008-05-20 06:58:21 +0000848 def winfo_interps(self, displayof=0):
849 """Return the name of all Tcl interpreters for this display."""
850 args = ('winfo', 'interps') + self._displayof(displayof)
851 return self.tk.splitlist(self.tk.call(args))
852 def winfo_ismapped(self):
853 """Return true if this widget is mapped."""
854 return getint(
855 self.tk.call('winfo', 'ismapped', self._w))
856 def winfo_manager(self):
Vijay Kumarf31f2252017-05-23 11:46:27 +0530857 """Return the window manager name for this widget."""
Georg Brandl33cece02008-05-20 06:58:21 +0000858 return self.tk.call('winfo', 'manager', self._w)
859 def winfo_name(self):
860 """Return the name of this widget."""
861 return self.tk.call('winfo', 'name', self._w)
862 def winfo_parent(self):
863 """Return the name of the parent of this widget."""
864 return self.tk.call('winfo', 'parent', self._w)
865 def winfo_pathname(self, id, displayof=0):
866 """Return the pathname of the widget given by ID."""
867 args = ('winfo', 'pathname') \
868 + self._displayof(displayof) + (id,)
869 return self.tk.call(args)
870 def winfo_pixels(self, number):
871 """Rounded integer value of winfo_fpixels."""
872 return getint(
873 self.tk.call('winfo', 'pixels', self._w, number))
874 def winfo_pointerx(self):
875 """Return the x coordinate of the pointer on the root window."""
876 return getint(
877 self.tk.call('winfo', 'pointerx', self._w))
878 def winfo_pointerxy(self):
879 """Return a tuple of x and y coordinates of the pointer on the root window."""
880 return self._getints(
881 self.tk.call('winfo', 'pointerxy', self._w))
882 def winfo_pointery(self):
883 """Return the y coordinate of the pointer on the root window."""
884 return getint(
885 self.tk.call('winfo', 'pointery', self._w))
886 def winfo_reqheight(self):
887 """Return requested height of this widget."""
888 return getint(
889 self.tk.call('winfo', 'reqheight', self._w))
890 def winfo_reqwidth(self):
891 """Return requested width of this widget."""
892 return getint(
893 self.tk.call('winfo', 'reqwidth', self._w))
894 def winfo_rgb(self, color):
895 """Return tuple of decimal values for red, green, blue for
896 COLOR in this widget."""
897 return self._getints(
898 self.tk.call('winfo', 'rgb', self._w, color))
899 def winfo_rootx(self):
900 """Return x coordinate of upper left corner of this widget on the
901 root window."""
902 return getint(
903 self.tk.call('winfo', 'rootx', self._w))
904 def winfo_rooty(self):
905 """Return y coordinate of upper left corner of this widget on the
906 root window."""
907 return getint(
908 self.tk.call('winfo', 'rooty', self._w))
909 def winfo_screen(self):
910 """Return the screen name of this widget."""
911 return self.tk.call('winfo', 'screen', self._w)
912 def winfo_screencells(self):
913 """Return the number of the cells in the colormap of the screen
914 of this widget."""
915 return getint(
916 self.tk.call('winfo', 'screencells', self._w))
917 def winfo_screendepth(self):
918 """Return the number of bits per pixel of the root window of the
919 screen of this widget."""
920 return getint(
921 self.tk.call('winfo', 'screendepth', self._w))
922 def winfo_screenheight(self):
923 """Return the number of pixels of the height of the screen of this widget
924 in pixel."""
925 return getint(
926 self.tk.call('winfo', 'screenheight', self._w))
927 def winfo_screenmmheight(self):
928 """Return the number of pixels of the height of the screen of
929 this widget in mm."""
930 return getint(
931 self.tk.call('winfo', 'screenmmheight', self._w))
932 def winfo_screenmmwidth(self):
933 """Return the number of pixels of the width of the screen of
934 this widget in mm."""
935 return getint(
936 self.tk.call('winfo', 'screenmmwidth', self._w))
937 def winfo_screenvisual(self):
938 """Return one of the strings directcolor, grayscale, pseudocolor,
939 staticcolor, staticgray, or truecolor for the default
940 colormodel of this screen."""
941 return self.tk.call('winfo', 'screenvisual', self._w)
942 def winfo_screenwidth(self):
943 """Return the number of pixels of the width of the screen of
944 this widget in pixel."""
945 return getint(
946 self.tk.call('winfo', 'screenwidth', self._w))
947 def winfo_server(self):
948 """Return information of the X-Server of the screen of this widget in
949 the form "XmajorRminor vendor vendorVersion"."""
950 return self.tk.call('winfo', 'server', self._w)
951 def winfo_toplevel(self):
952 """Return the toplevel widget of this widget."""
953 return self._nametowidget(self.tk.call(
954 'winfo', 'toplevel', self._w))
955 def winfo_viewable(self):
956 """Return true if the widget and all its higher ancestors are mapped."""
957 return getint(
958 self.tk.call('winfo', 'viewable', self._w))
959 def winfo_visual(self):
960 """Return one of the strings directcolor, grayscale, pseudocolor,
961 staticcolor, staticgray, or truecolor for the
962 colormodel of this widget."""
963 return self.tk.call('winfo', 'visual', self._w)
964 def winfo_visualid(self):
965 """Return the X identifier for the visual for this widget."""
966 return self.tk.call('winfo', 'visualid', self._w)
967 def winfo_visualsavailable(self, includeids=0):
968 """Return a list of all visuals available for the screen
969 of this widget.
970
971 Each item in the list consists of a visual name (see winfo_visual), a
972 depth and if INCLUDEIDS=1 is given also the X identifier."""
973 data = self.tk.split(
974 self.tk.call('winfo', 'visualsavailable', self._w,
975 includeids and 'includeids' or None))
976 if type(data) is StringType:
977 data = [self.tk.split(data)]
978 return map(self.__winfo_parseitem, data)
979 def __winfo_parseitem(self, t):
980 """Internal function."""
981 return t[:1] + tuple(map(self.__winfo_getint, t[1:]))
982 def __winfo_getint(self, x):
983 """Internal function."""
984 return int(x, 0)
985 def winfo_vrootheight(self):
986 """Return the height of the virtual root window associated with this
987 widget in pixels. If there is no virtual root window return the
988 height of the screen."""
989 return getint(
990 self.tk.call('winfo', 'vrootheight', self._w))
991 def winfo_vrootwidth(self):
992 """Return the width of the virtual root window associated with this
993 widget in pixel. If there is no virtual root window return the
994 width of the screen."""
995 return getint(
996 self.tk.call('winfo', 'vrootwidth', self._w))
997 def winfo_vrootx(self):
998 """Return the x offset of the virtual root relative to the root
999 window of the screen of this widget."""
1000 return getint(
1001 self.tk.call('winfo', 'vrootx', self._w))
1002 def winfo_vrooty(self):
1003 """Return the y offset of the virtual root relative to the root
1004 window of the screen of this widget."""
1005 return getint(
1006 self.tk.call('winfo', 'vrooty', self._w))
1007 def winfo_width(self):
1008 """Return the width of this widget."""
1009 return getint(
1010 self.tk.call('winfo', 'width', self._w))
1011 def winfo_x(self):
1012 """Return the x coordinate of the upper left corner of this widget
1013 in the parent."""
1014 return getint(
1015 self.tk.call('winfo', 'x', self._w))
1016 def winfo_y(self):
1017 """Return the y coordinate of the upper left corner of this widget
1018 in the parent."""
1019 return getint(
1020 self.tk.call('winfo', 'y', self._w))
1021 def update(self):
1022 """Enter event loop until all pending events have been processed by Tcl."""
1023 self.tk.call('update')
1024 def update_idletasks(self):
1025 """Enter event loop until all idle callbacks have been called. This
1026 will update the display of windows but not process events caused by
1027 the user."""
1028 self.tk.call('update', 'idletasks')
1029 def bindtags(self, tagList=None):
1030 """Set or get the list of bindtags for this widget.
1031
1032 With no argument return the list of all bindtags associated with
1033 this widget. With a list of strings as argument the bindtags are
1034 set to this list. The bindtags determine in which order events are
1035 processed (see bind)."""
1036 if tagList is None:
1037 return self.tk.splitlist(
1038 self.tk.call('bindtags', self._w))
1039 else:
1040 self.tk.call('bindtags', self._w, tagList)
1041 def _bind(self, what, sequence, func, add, needcleanup=1):
1042 """Internal function."""
1043 if type(func) is StringType:
1044 self.tk.call(what + (sequence, func))
1045 elif func:
1046 funcid = self._register(func, self._substitute,
1047 needcleanup)
1048 cmd = ('%sif {"[%s %s]" == "break"} break\n'
1049 %
1050 (add and '+' or '',
1051 funcid, self._subst_format_str))
1052 self.tk.call(what + (sequence, cmd))
1053 return funcid
1054 elif sequence:
1055 return self.tk.call(what + (sequence,))
1056 else:
1057 return self.tk.splitlist(self.tk.call(what))
1058 def bind(self, sequence=None, func=None, add=None):
1059 """Bind to this widget at event SEQUENCE a call to function FUNC.
1060
1061 SEQUENCE is a string of concatenated event
1062 patterns. An event pattern is of the form
1063 <MODIFIER-MODIFIER-TYPE-DETAIL> where MODIFIER is one
1064 of Control, Mod2, M2, Shift, Mod3, M3, Lock, Mod4, M4,
1065 Button1, B1, Mod5, M5 Button2, B2, Meta, M, Button3,
1066 B3, Alt, Button4, B4, Double, Button5, B5 Triple,
1067 Mod1, M1. TYPE is one of Activate, Enter, Map,
1068 ButtonPress, Button, Expose, Motion, ButtonRelease
1069 FocusIn, MouseWheel, Circulate, FocusOut, Property,
1070 Colormap, Gravity Reparent, Configure, KeyPress, Key,
1071 Unmap, Deactivate, KeyRelease Visibility, Destroy,
1072 Leave and DETAIL is the button number for ButtonPress,
1073 ButtonRelease and DETAIL is the Keysym for KeyPress and
1074 KeyRelease. Examples are
1075 <Control-Button-1> for pressing Control and mouse button 1 or
1076 <Alt-A> for pressing A and the Alt key (KeyPress can be omitted).
1077 An event pattern can also be a virtual event of the form
1078 <<AString>> where AString can be arbitrary. This
1079 event can be generated by event_generate.
1080 If events are concatenated they must appear shortly
1081 after each other.
1082
1083 FUNC will be called if the event sequence occurs with an
1084 instance of Event as argument. If the return value of FUNC is
1085 "break" no further bound function is invoked.
1086
1087 An additional boolean parameter ADD specifies whether FUNC will
1088 be called additionally to the other bound function or whether
1089 it will replace the previous function.
1090
1091 Bind will return an identifier to allow deletion of the bound function with
1092 unbind without memory leak.
1093
1094 If FUNC or SEQUENCE is omitted the bound function or list
1095 of bound events are returned."""
1096
1097 return self._bind(('bind', self._w), sequence, func, add)
1098 def unbind(self, sequence, funcid=None):
1099 """Unbind for this widget for event SEQUENCE the
1100 function identified with FUNCID."""
1101 self.tk.call('bind', self._w, sequence, '')
1102 if funcid:
1103 self.deletecommand(funcid)
1104 def bind_all(self, sequence=None, func=None, add=None):
1105 """Bind to all widgets at an event SEQUENCE a call to function FUNC.
1106 An additional boolean parameter ADD specifies whether FUNC will
1107 be called additionally to the other bound function or whether
1108 it will replace the previous function. See bind for the return value."""
1109 return self._bind(('bind', 'all'), sequence, func, add, 0)
1110 def unbind_all(self, sequence):
1111 """Unbind for all widgets for event SEQUENCE all functions."""
1112 self.tk.call('bind', 'all' , sequence, '')
1113 def bind_class(self, className, sequence=None, func=None, add=None):
1114
1115 """Bind to widgets with bindtag CLASSNAME at event
1116 SEQUENCE a call of function FUNC. An additional
1117 boolean parameter ADD specifies whether FUNC will be
1118 called additionally to the other bound function or
1119 whether it will replace the previous function. See bind for
1120 the return value."""
1121
1122 return self._bind(('bind', className), sequence, func, add, 0)
1123 def unbind_class(self, className, sequence):
Serhiy Storchakac72e66a2015-11-02 15:06:09 +02001124 """Unbind for all widgets with bindtag CLASSNAME for event SEQUENCE
Georg Brandl33cece02008-05-20 06:58:21 +00001125 all functions."""
1126 self.tk.call('bind', className , sequence, '')
1127 def mainloop(self, n=0):
1128 """Call the mainloop of Tk."""
1129 self.tk.mainloop(n)
1130 def quit(self):
1131 """Quit the Tcl interpreter. All widgets will be destroyed."""
1132 self.tk.quit()
1133 def _getints(self, string):
1134 """Internal function."""
1135 if string:
1136 return tuple(map(getint, self.tk.splitlist(string)))
1137 def _getdoubles(self, string):
1138 """Internal function."""
1139 if string:
1140 return tuple(map(getdouble, self.tk.splitlist(string)))
1141 def _getboolean(self, string):
1142 """Internal function."""
1143 if string:
1144 return self.tk.getboolean(string)
1145 def _displayof(self, displayof):
1146 """Internal function."""
1147 if displayof:
1148 return ('-displayof', displayof)
1149 if displayof is None:
1150 return ('-displayof', self._w)
1151 return ()
Ned Deily724a55c2012-05-15 18:05:57 -07001152 @property
1153 def _windowingsystem(self):
1154 """Internal function."""
1155 try:
1156 return self._root()._windowingsystem_cached
1157 except AttributeError:
1158 ws = self._root()._windowingsystem_cached = \
1159 self.tk.call('tk', 'windowingsystem')
1160 return ws
Georg Brandl33cece02008-05-20 06:58:21 +00001161 def _options(self, cnf, kw = None):
1162 """Internal function."""
1163 if kw:
1164 cnf = _cnfmerge((cnf, kw))
1165 else:
1166 cnf = _cnfmerge(cnf)
1167 res = ()
1168 for k, v in cnf.items():
1169 if v is not None:
1170 if k[-1] == '_': k = k[:-1]
Benjamin Petersonde055992009-10-09 22:05:45 +00001171 if hasattr(v, '__call__'):
Georg Brandl33cece02008-05-20 06:58:21 +00001172 v = self._register(v)
Georg Brandl7943a322008-05-29 07:18:49 +00001173 elif isinstance(v, (tuple, list)):
Georg Brandl4ed3ed12008-06-03 10:23:15 +00001174 nv = []
Georg Brandl7943a322008-05-29 07:18:49 +00001175 for item in v:
Serhiy Storchaka994f04d2016-12-27 15:09:36 +02001176 if not isinstance(item, (basestring, int, long)):
Georg Brandl7943a322008-05-29 07:18:49 +00001177 break
Serhiy Storchaka994f04d2016-12-27 15:09:36 +02001178 elif isinstance(item, (int, long)):
Georg Brandl4ed3ed12008-06-03 10:23:15 +00001179 nv.append('%d' % item)
1180 else:
1181 # format it to proper Tcl code if it contains space
Serhiy Storchakae39ba042013-01-15 18:01:21 +02001182 nv.append(_stringify(item))
Georg Brandl7943a322008-05-29 07:18:49 +00001183 else:
Georg Brandl4ed3ed12008-06-03 10:23:15 +00001184 v = ' '.join(nv)
Georg Brandl33cece02008-05-20 06:58:21 +00001185 res = res + ('-'+k, v)
1186 return res
1187 def nametowidget(self, name):
1188 """Return the Tkinter instance of a widget identified by
1189 its Tcl name NAME."""
Martin v. Löwisaabf4042008-08-02 07:20:25 +00001190 name = str(name).split('.')
Georg Brandl33cece02008-05-20 06:58:21 +00001191 w = self
Martin v. Löwisaabf4042008-08-02 07:20:25 +00001192
1193 if not name[0]:
Georg Brandl33cece02008-05-20 06:58:21 +00001194 w = w._root()
1195 name = name[1:]
Martin v. Löwisaabf4042008-08-02 07:20:25 +00001196
1197 for n in name:
1198 if not n:
1199 break
1200 w = w.children[n]
1201
Georg Brandl33cece02008-05-20 06:58:21 +00001202 return w
1203 _nametowidget = nametowidget
1204 def _register(self, func, subst=None, needcleanup=1):
1205 """Return a newly created Tcl function. If this
1206 function is called, the Python function FUNC will
1207 be executed. An optional function SUBST can
1208 be given which will be executed before FUNC."""
1209 f = CallWrapper(func, subst, self).__call__
1210 name = repr(id(f))
1211 try:
1212 func = func.im_func
1213 except AttributeError:
1214 pass
1215 try:
1216 name = name + func.__name__
1217 except AttributeError:
1218 pass
1219 self.tk.createcommand(name, f)
1220 if needcleanup:
1221 if self._tclCommands is None:
1222 self._tclCommands = []
1223 self._tclCommands.append(name)
Georg Brandl33cece02008-05-20 06:58:21 +00001224 return name
1225 register = _register
1226 def _root(self):
1227 """Internal function."""
1228 w = self
1229 while w.master: w = w.master
1230 return w
1231 _subst_format = ('%#', '%b', '%f', '%h', '%k',
1232 '%s', '%t', '%w', '%x', '%y',
1233 '%A', '%E', '%K', '%N', '%W', '%T', '%X', '%Y', '%D')
1234 _subst_format_str = " ".join(_subst_format)
1235 def _substitute(self, *args):
1236 """Internal function."""
1237 if len(args) != len(self._subst_format): return args
1238 getboolean = self.tk.getboolean
1239
1240 getint = int
1241 def getint_event(s):
1242 """Tk changed behavior in 8.4.2, returning "??" rather more often."""
1243 try:
1244 return int(s)
1245 except ValueError:
1246 return s
1247
1248 nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args
1249 # Missing: (a, c, d, m, o, v, B, R)
1250 e = Event()
Martin Panterf2f1c572016-05-08 13:18:25 +00001251 # serial field: valid for all events
Georg Brandl33cece02008-05-20 06:58:21 +00001252 # number of button: ButtonPress and ButtonRelease events only
1253 # height field: Configure, ConfigureRequest, Create,
1254 # ResizeRequest, and Expose events only
1255 # keycode field: KeyPress and KeyRelease events only
1256 # time field: "valid for events that contain a time field"
1257 # width field: Configure, ConfigureRequest, Create, ResizeRequest,
1258 # and Expose events only
Martin Panter4f23cab2016-05-08 13:45:55 +00001259 # x field: "valid for events that contain an x field"
Georg Brandl33cece02008-05-20 06:58:21 +00001260 # y field: "valid for events that contain a y field"
1261 # keysym as decimal: KeyPress and KeyRelease events only
1262 # x_root, y_root fields: ButtonPress, ButtonRelease, KeyPress,
Martin Panterf2f1c572016-05-08 13:18:25 +00001263 # KeyRelease, and Motion events
Georg Brandl33cece02008-05-20 06:58:21 +00001264 e.serial = getint(nsign)
1265 e.num = getint_event(b)
1266 try: e.focus = getboolean(f)
1267 except TclError: pass
1268 e.height = getint_event(h)
1269 e.keycode = getint_event(k)
1270 e.state = getint_event(s)
1271 e.time = getint_event(t)
1272 e.width = getint_event(w)
1273 e.x = getint_event(x)
1274 e.y = getint_event(y)
1275 e.char = A
1276 try: e.send_event = getboolean(E)
1277 except TclError: pass
1278 e.keysym = K
1279 e.keysym_num = getint_event(N)
1280 e.type = T
1281 try:
1282 e.widget = self._nametowidget(W)
1283 except KeyError:
1284 e.widget = W
1285 e.x_root = getint_event(X)
1286 e.y_root = getint_event(Y)
1287 try:
1288 e.delta = getint(D)
1289 except ValueError:
1290 e.delta = 0
1291 return (e,)
1292 def _report_exception(self):
1293 """Internal function."""
1294 import sys
1295 exc, val, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
1296 root = self._root()
1297 root.report_callback_exception(exc, val, tb)
Serhiy Storchakaec773cc2013-12-25 16:35:20 +02001298
1299 def _getconfigure(self, *args):
1300 """Call Tcl configure command and return the result as a dict."""
1301 cnf = {}
1302 for x in self.tk.splitlist(self.tk.call(*args)):
1303 x = self.tk.splitlist(x)
1304 cnf[x[0][1:]] = (x[0][1:],) + x[1:]
1305 return cnf
1306
1307 def _getconfigure1(self, *args):
1308 x = self.tk.splitlist(self.tk.call(*args))
1309 return (x[0][1:],) + x[1:]
1310
Georg Brandl33cece02008-05-20 06:58:21 +00001311 def _configure(self, cmd, cnf, kw):
1312 """Internal function."""
1313 if kw:
1314 cnf = _cnfmerge((cnf, kw))
1315 elif cnf:
1316 cnf = _cnfmerge(cnf)
1317 if cnf is None:
Serhiy Storchakaec773cc2013-12-25 16:35:20 +02001318 return self._getconfigure(_flatten((self._w, cmd)))
Georg Brandl33cece02008-05-20 06:58:21 +00001319 if type(cnf) is StringType:
Serhiy Storchakaec773cc2013-12-25 16:35:20 +02001320 return self._getconfigure1(_flatten((self._w, cmd, '-'+cnf)))
Georg Brandl33cece02008-05-20 06:58:21 +00001321 self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
1322 # These used to be defined in Widget:
1323 def configure(self, cnf=None, **kw):
1324 """Configure resources of a widget.
1325
1326 The values for resources are specified as keyword
1327 arguments. To get an overview about
1328 the allowed keyword arguments call the method keys.
1329 """
1330 return self._configure('configure', cnf, kw)
1331 config = configure
1332 def cget(self, key):
1333 """Return the resource value for a KEY given as string."""
Georg Brandl33cece02008-05-20 06:58:21 +00001334 return self.tk.call(self._w, 'cget', '-' + key)
1335 __getitem__ = cget
1336 def __setitem__(self, key, value):
1337 self.configure({key: value})
Georg Brandlae019e12008-05-20 08:48:34 +00001338 def __contains__(self, key):
1339 raise TypeError("Tkinter objects don't support 'in' tests.")
Georg Brandl33cece02008-05-20 06:58:21 +00001340 def keys(self):
1341 """Return a list of all resource names of this widget."""
Serhiy Storchaka0fd213c2016-03-09 10:51:41 +02001342 splitlist = self.tk.splitlist
1343 return [splitlist(x)[0][1:] for x in
1344 splitlist(self.tk.call(self._w, 'configure'))]
Georg Brandl33cece02008-05-20 06:58:21 +00001345 def __str__(self):
1346 """Return the window path name of this widget."""
1347 return self._w
1348 # Pack methods that apply to the master
1349 _noarg_ = ['_noarg_']
1350 def pack_propagate(self, flag=_noarg_):
1351 """Set or get the status for propagation of geometry information.
1352
1353 A boolean argument specifies whether the geometry information
1354 of the slaves will determine the size of this widget. If no argument
1355 is given the current setting will be returned.
1356 """
1357 if flag is Misc._noarg_:
1358 return self._getboolean(self.tk.call(
1359 'pack', 'propagate', self._w))
1360 else:
1361 self.tk.call('pack', 'propagate', self._w, flag)
1362 propagate = pack_propagate
1363 def pack_slaves(self):
1364 """Return a list of all slaves of this widget
1365 in its packing order."""
1366 return map(self._nametowidget,
1367 self.tk.splitlist(
1368 self.tk.call('pack', 'slaves', self._w)))
1369 slaves = pack_slaves
1370 # Place method that applies to the master
1371 def place_slaves(self):
1372 """Return a list of all slaves of this widget
1373 in its packing order."""
1374 return map(self._nametowidget,
1375 self.tk.splitlist(
1376 self.tk.call(
1377 'place', 'slaves', self._w)))
1378 # Grid methods that apply to the master
1379 def grid_bbox(self, column=None, row=None, col2=None, row2=None):
1380 """Return a tuple of integer coordinates for the bounding
1381 box of this widget controlled by the geometry manager grid.
1382
1383 If COLUMN, ROW is given the bounding box applies from
1384 the cell with row and column 0 to the specified
1385 cell. If COL2 and ROW2 are given the bounding box
1386 starts at that cell.
1387
1388 The returned integers specify the offset of the upper left
1389 corner in the master widget and the width and height.
1390 """
1391 args = ('grid', 'bbox', self._w)
1392 if column is not None and row is not None:
1393 args = args + (column, row)
1394 if col2 is not None and row2 is not None:
1395 args = args + (col2, row2)
1396 return self._getints(self.tk.call(*args)) or None
1397
1398 bbox = grid_bbox
Serhiy Storchaka3e0cb092014-02-19 18:33:30 +02001399
1400 def _gridconvvalue(self, value):
1401 if isinstance(value, (str, _tkinter.Tcl_Obj)):
1402 try:
1403 svalue = str(value)
1404 if not svalue:
1405 return None
1406 elif '.' in svalue:
1407 return getdouble(svalue)
1408 else:
1409 return getint(svalue)
1410 except ValueError:
1411 pass
1412 return value
1413
Georg Brandl33cece02008-05-20 06:58:21 +00001414 def _grid_configure(self, command, index, cnf, kw):
1415 """Internal function."""
1416 if type(cnf) is StringType and not kw:
1417 if cnf[-1:] == '_':
1418 cnf = cnf[:-1]
1419 if cnf[:1] != '-':
1420 cnf = '-'+cnf
1421 options = (cnf,)
1422 else:
1423 options = self._options(cnf, kw)
1424 if not options:
Serhiy Storchakaceaf6822014-09-06 22:47:02 +03001425 return _splitdict(
1426 self.tk,
1427 self.tk.call('grid', command, self._w, index),
1428 conv=self._gridconvvalue)
Georg Brandl33cece02008-05-20 06:58:21 +00001429 res = self.tk.call(
1430 ('grid', command, self._w, index)
1431 + options)
1432 if len(options) == 1:
Serhiy Storchaka3e0cb092014-02-19 18:33:30 +02001433 return self._gridconvvalue(res)
1434
Georg Brandl33cece02008-05-20 06:58:21 +00001435 def grid_columnconfigure(self, index, cnf={}, **kw):
1436 """Configure column INDEX of a grid.
1437
1438 Valid resources are minsize (minimum size of the column),
1439 weight (how much does additional space propagate to this column)
1440 and pad (how much space to let additionally)."""
1441 return self._grid_configure('columnconfigure', index, cnf, kw)
1442 columnconfigure = grid_columnconfigure
1443 def grid_location(self, x, y):
1444 """Return a tuple of column and row which identify the cell
1445 at which the pixel at position X and Y inside the master
1446 widget is located."""
1447 return self._getints(
1448 self.tk.call(
1449 'grid', 'location', self._w, x, y)) or None
1450 def grid_propagate(self, flag=_noarg_):
1451 """Set or get the status for propagation of geometry information.
1452
1453 A boolean argument specifies whether the geometry information
1454 of the slaves will determine the size of this widget. If no argument
1455 is given, the current setting will be returned.
1456 """
1457 if flag is Misc._noarg_:
1458 return self._getboolean(self.tk.call(
1459 'grid', 'propagate', self._w))
1460 else:
1461 self.tk.call('grid', 'propagate', self._w, flag)
1462 def grid_rowconfigure(self, index, cnf={}, **kw):
1463 """Configure row INDEX of a grid.
1464
1465 Valid resources are minsize (minimum size of the row),
1466 weight (how much does additional space propagate to this row)
1467 and pad (how much space to let additionally)."""
1468 return self._grid_configure('rowconfigure', index, cnf, kw)
1469 rowconfigure = grid_rowconfigure
1470 def grid_size(self):
1471 """Return a tuple of the number of column and rows in the grid."""
1472 return self._getints(
1473 self.tk.call('grid', 'size', self._w)) or None
1474 size = grid_size
1475 def grid_slaves(self, row=None, column=None):
1476 """Return a list of all slaves of this widget
1477 in its packing order."""
1478 args = ()
1479 if row is not None:
1480 args = args + ('-row', row)
1481 if column is not None:
1482 args = args + ('-column', column)
1483 return map(self._nametowidget,
1484 self.tk.splitlist(self.tk.call(
1485 ('grid', 'slaves', self._w) + args)))
1486
1487 # Support for the "event" command, new in Tk 4.2.
1488 # By Case Roole.
1489
1490 def event_add(self, virtual, *sequences):
1491 """Bind a virtual event VIRTUAL (of the form <<Name>>)
1492 to an event SEQUENCE such that the virtual event is triggered
1493 whenever SEQUENCE occurs."""
1494 args = ('event', 'add', virtual) + sequences
1495 self.tk.call(args)
1496
1497 def event_delete(self, virtual, *sequences):
1498 """Unbind a virtual event VIRTUAL from SEQUENCE."""
1499 args = ('event', 'delete', virtual) + sequences
1500 self.tk.call(args)
1501
1502 def event_generate(self, sequence, **kw):
1503 """Generate an event SEQUENCE. Additional
1504 keyword arguments specify parameter of the event
1505 (e.g. x, y, rootx, rooty)."""
1506 args = ('event', 'generate', self._w, sequence)
1507 for k, v in kw.items():
1508 args = args + ('-%s' % k, str(v))
1509 self.tk.call(args)
1510
1511 def event_info(self, virtual=None):
1512 """Return a list of all virtual events or the information
1513 about the SEQUENCE bound to the virtual event VIRTUAL."""
1514 return self.tk.splitlist(
1515 self.tk.call('event', 'info', virtual))
1516
1517 # Image related commands
1518
1519 def image_names(self):
1520 """Return a list of all existing image names."""
Serhiy Storchaka9be238d2014-01-07 19:32:58 +02001521 return self.tk.splitlist(self.tk.call('image', 'names'))
Georg Brandl33cece02008-05-20 06:58:21 +00001522
1523 def image_types(self):
Vijay Kumarf31f2252017-05-23 11:46:27 +05301524 """Return a list of all available image types (e.g. photo bitmap)."""
Serhiy Storchaka9be238d2014-01-07 19:32:58 +02001525 return self.tk.splitlist(self.tk.call('image', 'types'))
Georg Brandl33cece02008-05-20 06:58:21 +00001526
1527
1528class CallWrapper:
1529 """Internal class. Stores function to call when some user
1530 defined Tcl function is called e.g. after an event occurred."""
1531 def __init__(self, func, subst, widget):
1532 """Store FUNC, SUBST and WIDGET as members."""
1533 self.func = func
1534 self.subst = subst
1535 self.widget = widget
1536 def __call__(self, *args):
1537 """Apply first function SUBST to arguments, than FUNC."""
1538 try:
1539 if self.subst:
1540 args = self.subst(*args)
1541 return self.func(*args)
1542 except SystemExit, msg:
1543 raise SystemExit, msg
1544 except:
1545 self.widget._report_exception()
1546
1547
Guilherme Poloe45f0172009-08-14 14:36:45 +00001548class XView:
1549 """Mix-in class for querying and changing the horizontal position
1550 of a widget's window."""
1551
1552 def xview(self, *args):
1553 """Query and change the horizontal position of the view."""
1554 res = self.tk.call(self._w, 'xview', *args)
1555 if not args:
1556 return self._getdoubles(res)
1557
1558 def xview_moveto(self, fraction):
1559 """Adjusts the view in the window so that FRACTION of the
1560 total width of the canvas is off-screen to the left."""
1561 self.tk.call(self._w, 'xview', 'moveto', fraction)
1562
1563 def xview_scroll(self, number, what):
1564 """Shift the x-view according to NUMBER which is measured in "units"
1565 or "pages" (WHAT)."""
1566 self.tk.call(self._w, 'xview', 'scroll', number, what)
1567
1568
1569class YView:
1570 """Mix-in class for querying and changing the vertical position
1571 of a widget's window."""
1572
1573 def yview(self, *args):
1574 """Query and change the vertical position of the view."""
1575 res = self.tk.call(self._w, 'yview', *args)
1576 if not args:
1577 return self._getdoubles(res)
1578
1579 def yview_moveto(self, fraction):
1580 """Adjusts the view in the window so that FRACTION of the
1581 total height of the canvas is off-screen to the top."""
1582 self.tk.call(self._w, 'yview', 'moveto', fraction)
1583
1584 def yview_scroll(self, number, what):
1585 """Shift the y-view according to NUMBER which is measured in
1586 "units" or "pages" (WHAT)."""
1587 self.tk.call(self._w, 'yview', 'scroll', number, what)
1588
1589
Georg Brandl33cece02008-05-20 06:58:21 +00001590class Wm:
1591 """Provides functions for the communication with the window manager."""
1592
1593 def wm_aspect(self,
1594 minNumer=None, minDenom=None,
1595 maxNumer=None, maxDenom=None):
1596 """Instruct the window manager to set the aspect ratio (width/height)
1597 of this widget to be between MINNUMER/MINDENOM and MAXNUMER/MAXDENOM. Return a tuple
1598 of the actual values if no argument is given."""
1599 return self._getints(
1600 self.tk.call('wm', 'aspect', self._w,
1601 minNumer, minDenom,
1602 maxNumer, maxDenom))
1603 aspect = wm_aspect
1604
1605 def wm_attributes(self, *args):
1606 """This subcommand returns or sets platform specific attributes
1607
1608 The first form returns a list of the platform specific flags and
1609 their values. The second form returns the value for the specific
1610 option. The third form sets one or more of the values. The values
1611 are as follows:
1612
1613 On Windows, -disabled gets or sets whether the window is in a
1614 disabled state. -toolwindow gets or sets the style of the window
1615 to toolwindow (as defined in the MSDN). -topmost gets or sets
1616 whether this is a topmost window (displays above all other
1617 windows).
1618
1619 On Macintosh, XXXXX
1620
1621 On Unix, there are currently no special attribute values.
1622 """
1623 args = ('wm', 'attributes', self._w) + args
1624 return self.tk.call(args)
1625 attributes=wm_attributes
1626
1627 def wm_client(self, name=None):
1628 """Store NAME in WM_CLIENT_MACHINE property of this widget. Return
1629 current value."""
1630 return self.tk.call('wm', 'client', self._w, name)
1631 client = wm_client
1632 def wm_colormapwindows(self, *wlist):
1633 """Store list of window names (WLIST) into WM_COLORMAPWINDOWS property
1634 of this widget. This list contains windows whose colormaps differ from their
1635 parents. Return current list of widgets if WLIST is empty."""
1636 if len(wlist) > 1:
1637 wlist = (wlist,) # Tk needs a list of windows here
1638 args = ('wm', 'colormapwindows', self._w) + wlist
Serhiy Storchaka9be238d2014-01-07 19:32:58 +02001639 if wlist:
1640 self.tk.call(args)
1641 else:
1642 return map(self._nametowidget, self.tk.splitlist(self.tk.call(args)))
Georg Brandl33cece02008-05-20 06:58:21 +00001643 colormapwindows = wm_colormapwindows
1644 def wm_command(self, value=None):
1645 """Store VALUE in WM_COMMAND property. It is the command
1646 which shall be used to invoke the application. Return current
1647 command if VALUE is None."""
1648 return self.tk.call('wm', 'command', self._w, value)
1649 command = wm_command
1650 def wm_deiconify(self):
1651 """Deiconify this widget. If it was never mapped it will not be mapped.
1652 On Windows it will raise this widget and give it the focus."""
1653 return self.tk.call('wm', 'deiconify', self._w)
1654 deiconify = wm_deiconify
1655 def wm_focusmodel(self, model=None):
1656 """Set focus model to MODEL. "active" means that this widget will claim
1657 the focus itself, "passive" means that the window manager shall give
1658 the focus. Return current focus model if MODEL is None."""
1659 return self.tk.call('wm', 'focusmodel', self._w, model)
1660 focusmodel = wm_focusmodel
1661 def wm_frame(self):
1662 """Return identifier for decorative frame of this widget if present."""
1663 return self.tk.call('wm', 'frame', self._w)
1664 frame = wm_frame
1665 def wm_geometry(self, newGeometry=None):
1666 """Set geometry to NEWGEOMETRY of the form =widthxheight+x+y. Return
1667 current value if None is given."""
1668 return self.tk.call('wm', 'geometry', self._w, newGeometry)
1669 geometry = wm_geometry
1670 def wm_grid(self,
1671 baseWidth=None, baseHeight=None,
1672 widthInc=None, heightInc=None):
1673 """Instruct the window manager that this widget shall only be
1674 resized on grid boundaries. WIDTHINC and HEIGHTINC are the width and
1675 height of a grid unit in pixels. BASEWIDTH and BASEHEIGHT are the
1676 number of grid units requested in Tk_GeometryRequest."""
1677 return self._getints(self.tk.call(
1678 'wm', 'grid', self._w,
1679 baseWidth, baseHeight, widthInc, heightInc))
1680 grid = wm_grid
1681 def wm_group(self, pathName=None):
1682 """Set the group leader widgets for related widgets to PATHNAME. Return
1683 the group leader of this widget if None is given."""
1684 return self.tk.call('wm', 'group', self._w, pathName)
1685 group = wm_group
1686 def wm_iconbitmap(self, bitmap=None, default=None):
1687 """Set bitmap for the iconified widget to BITMAP. Return
1688 the bitmap if None is given.
1689
1690 Under Windows, the DEFAULT parameter can be used to set the icon
1691 for the widget and any descendents that don't have an icon set
1692 explicitly. DEFAULT can be the relative path to a .ico file
1693 (example: root.iconbitmap(default='myicon.ico') ). See Tk
1694 documentation for more information."""
1695 if default:
1696 return self.tk.call('wm', 'iconbitmap', self._w, '-default', default)
1697 else:
1698 return self.tk.call('wm', 'iconbitmap', self._w, bitmap)
1699 iconbitmap = wm_iconbitmap
1700 def wm_iconify(self):
1701 """Display widget as icon."""
1702 return self.tk.call('wm', 'iconify', self._w)
1703 iconify = wm_iconify
1704 def wm_iconmask(self, bitmap=None):
1705 """Set mask for the icon bitmap of this widget. Return the
1706 mask if None is given."""
1707 return self.tk.call('wm', 'iconmask', self._w, bitmap)
1708 iconmask = wm_iconmask
1709 def wm_iconname(self, newName=None):
1710 """Set the name of the icon for this widget. Return the name if
1711 None is given."""
1712 return self.tk.call('wm', 'iconname', self._w, newName)
1713 iconname = wm_iconname
1714 def wm_iconposition(self, x=None, y=None):
1715 """Set the position of the icon of this widget to X and Y. Return
1716 a tuple of the current values of X and X if None is given."""
1717 return self._getints(self.tk.call(
1718 'wm', 'iconposition', self._w, x, y))
1719 iconposition = wm_iconposition
1720 def wm_iconwindow(self, pathName=None):
1721 """Set widget PATHNAME to be displayed instead of icon. Return the current
1722 value if None is given."""
1723 return self.tk.call('wm', 'iconwindow', self._w, pathName)
1724 iconwindow = wm_iconwindow
1725 def wm_maxsize(self, width=None, height=None):
1726 """Set max WIDTH and HEIGHT for this widget. If the window is gridded
1727 the values are given in grid units. Return the current values if None
1728 is given."""
1729 return self._getints(self.tk.call(
1730 'wm', 'maxsize', self._w, width, height))
1731 maxsize = wm_maxsize
1732 def wm_minsize(self, width=None, height=None):
1733 """Set min WIDTH and HEIGHT for this widget. If the window is gridded
1734 the values are given in grid units. Return the current values if None
1735 is given."""
1736 return self._getints(self.tk.call(
1737 'wm', 'minsize', self._w, width, height))
1738 minsize = wm_minsize
1739 def wm_overrideredirect(self, boolean=None):
1740 """Instruct the window manager to ignore this widget
1741 if BOOLEAN is given with 1. Return the current value if None
1742 is given."""
1743 return self._getboolean(self.tk.call(
1744 'wm', 'overrideredirect', self._w, boolean))
1745 overrideredirect = wm_overrideredirect
1746 def wm_positionfrom(self, who=None):
1747 """Instruct the window manager that the position of this widget shall
1748 be defined by the user if WHO is "user", and by its own policy if WHO is
1749 "program"."""
1750 return self.tk.call('wm', 'positionfrom', self._w, who)
1751 positionfrom = wm_positionfrom
1752 def wm_protocol(self, name=None, func=None):
1753 """Bind function FUNC to command NAME for this widget.
1754 Return the function bound to NAME if None is given. NAME could be
1755 e.g. "WM_SAVE_YOURSELF" or "WM_DELETE_WINDOW"."""
Brett Cannonff6868c2008-08-04 21:24:43 +00001756 if hasattr(func, '__call__'):
Georg Brandl33cece02008-05-20 06:58:21 +00001757 command = self._register(func)
1758 else:
1759 command = func
1760 return self.tk.call(
1761 'wm', 'protocol', self._w, name, command)
1762 protocol = wm_protocol
1763 def wm_resizable(self, width=None, height=None):
1764 """Instruct the window manager whether this width can be resized
1765 in WIDTH or HEIGHT. Both values are boolean values."""
1766 return self.tk.call('wm', 'resizable', self._w, width, height)
1767 resizable = wm_resizable
1768 def wm_sizefrom(self, who=None):
1769 """Instruct the window manager that the size of this widget shall
1770 be defined by the user if WHO is "user", and by its own policy if WHO is
1771 "program"."""
1772 return self.tk.call('wm', 'sizefrom', self._w, who)
1773 sizefrom = wm_sizefrom
1774 def wm_state(self, newstate=None):
1775 """Query or set the state of this widget as one of normal, icon,
1776 iconic (see wm_iconwindow), withdrawn, or zoomed (Windows only)."""
1777 return self.tk.call('wm', 'state', self._w, newstate)
1778 state = wm_state
1779 def wm_title(self, string=None):
1780 """Set the title of this widget."""
1781 return self.tk.call('wm', 'title', self._w, string)
1782 title = wm_title
1783 def wm_transient(self, master=None):
1784 """Instruct the window manager that this widget is transient
1785 with regard to widget MASTER."""
1786 return self.tk.call('wm', 'transient', self._w, master)
1787 transient = wm_transient
1788 def wm_withdraw(self):
1789 """Withdraw this widget from the screen such that it is unmapped
1790 and forgotten by the window manager. Re-draw it with wm_deiconify."""
1791 return self.tk.call('wm', 'withdraw', self._w)
1792 withdraw = wm_withdraw
1793
1794
1795class Tk(Misc, Wm):
1796 """Toplevel widget of Tk which represents mostly the main window
Ezio Melotti24b07bc2011-03-15 18:55:01 +02001797 of an application. It has an associated Tcl interpreter."""
Georg Brandl33cece02008-05-20 06:58:21 +00001798 _w = '.'
1799 def __init__(self, screenName=None, baseName=None, className='Tk',
1800 useTk=1, sync=0, use=None):
1801 """Return a new Toplevel widget on screen SCREENNAME. A new Tcl interpreter will
1802 be created. BASENAME will be used for the identification of the profile file (see
1803 readprofile).
1804 It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME
1805 is the name of the widget class."""
1806 self.master = None
1807 self.children = {}
1808 self._tkloaded = 0
1809 # to avoid recursions in the getattr code in case of failure, we
1810 # ensure that self.tk is always _something_.
1811 self.tk = None
1812 if baseName is None:
Antoine Pitrouba7620c2013-08-01 22:25:12 +02001813 import os
Georg Brandl33cece02008-05-20 06:58:21 +00001814 baseName = os.path.basename(sys.argv[0])
1815 baseName, ext = os.path.splitext(baseName)
1816 if ext not in ('.py', '.pyc', '.pyo'):
1817 baseName = baseName + ext
1818 interactive = 0
1819 self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
1820 if useTk:
1821 self._loadtk()
Antoine Pitrou7dddec42012-12-09 14:46:18 +01001822 if not sys.flags.ignore_environment:
1823 # Issue #16248: Honor the -E flag to avoid code injection.
1824 self.readprofile(baseName, className)
Georg Brandl33cece02008-05-20 06:58:21 +00001825 def loadtk(self):
1826 if not self._tkloaded:
1827 self.tk.loadtk()
1828 self._loadtk()
1829 def _loadtk(self):
1830 self._tkloaded = 1
1831 global _default_root
Georg Brandl33cece02008-05-20 06:58:21 +00001832 # Version sanity checks
1833 tk_version = self.tk.getvar('tk_version')
1834 if tk_version != _tkinter.TK_VERSION:
1835 raise RuntimeError, \
1836 "tk.h version (%s) doesn't match libtk.a version (%s)" \
1837 % (_tkinter.TK_VERSION, tk_version)
1838 # Under unknown circumstances, tcl_version gets coerced to float
1839 tcl_version = str(self.tk.getvar('tcl_version'))
1840 if tcl_version != _tkinter.TCL_VERSION:
1841 raise RuntimeError, \
1842 "tcl.h version (%s) doesn't match libtcl.a version (%s)" \
1843 % (_tkinter.TCL_VERSION, tcl_version)
1844 if TkVersion < 4.0:
1845 raise RuntimeError, \
1846 "Tk 4.0 or higher is required; found Tk %s" \
1847 % str(TkVersion)
1848 # Create and register the tkerror and exit commands
1849 # We need to inline parts of _register here, _ register
1850 # would register differently-named commands.
1851 if self._tclCommands is None:
1852 self._tclCommands = []
1853 self.tk.createcommand('tkerror', _tkerror)
1854 self.tk.createcommand('exit', _exit)
1855 self._tclCommands.append('tkerror')
1856 self._tclCommands.append('exit')
1857 if _support_default_root and not _default_root:
1858 _default_root = self
1859 self.protocol("WM_DELETE_WINDOW", self.destroy)
1860 def destroy(self):
1861 """Destroy this and all descendants widgets. This will
1862 end the application of this Tcl interpreter."""
1863 for c in self.children.values(): c.destroy()
1864 self.tk.call('destroy', self._w)
1865 Misc.destroy(self)
1866 global _default_root
1867 if _support_default_root and _default_root is self:
1868 _default_root = None
1869 def readprofile(self, baseName, className):
1870 """Internal function. It reads BASENAME.tcl and CLASSNAME.tcl into
1871 the Tcl Interpreter and calls execfile on BASENAME.py and CLASSNAME.py if
1872 such a file exists in the home directory."""
1873 import os
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +00001874 if 'HOME' in os.environ: home = os.environ['HOME']
Georg Brandl33cece02008-05-20 06:58:21 +00001875 else: home = os.curdir
1876 class_tcl = os.path.join(home, '.%s.tcl' % className)
1877 class_py = os.path.join(home, '.%s.py' % className)
1878 base_tcl = os.path.join(home, '.%s.tcl' % baseName)
1879 base_py = os.path.join(home, '.%s.py' % baseName)
1880 dir = {'self': self}
Georg Brandl6634bf22008-05-20 07:13:37 +00001881 exec 'from Tkinter import *' in dir
Georg Brandl33cece02008-05-20 06:58:21 +00001882 if os.path.isfile(class_tcl):
1883 self.tk.call('source', class_tcl)
1884 if os.path.isfile(class_py):
1885 execfile(class_py, dir)
1886 if os.path.isfile(base_tcl):
1887 self.tk.call('source', base_tcl)
1888 if os.path.isfile(base_py):
1889 execfile(base_py, dir)
1890 def report_callback_exception(self, exc, val, tb):
Serhiy Storchaka2971c5e2014-09-14 21:17:16 +03001891 """Report callback exception on sys.stderr.
1892
1893 Applications may want to override this internal function, and
1894 should when sys.stderr is None."""
Georg Brandl33cece02008-05-20 06:58:21 +00001895 import traceback, sys
Serhiy Storchaka2971c5e2014-09-14 21:17:16 +03001896 print >>sys.stderr, "Exception in Tkinter callback"
Georg Brandl33cece02008-05-20 06:58:21 +00001897 sys.last_type = exc
1898 sys.last_value = val
1899 sys.last_traceback = tb
1900 traceback.print_exception(exc, val, tb)
1901 def __getattr__(self, attr):
1902 "Delegate attribute access to the interpreter object"
1903 return getattr(self.tk, attr)
1904
1905# Ideally, the classes Pack, Place and Grid disappear, the
1906# pack/place/grid methods are defined on the Widget class, and
1907# everybody uses w.pack_whatever(...) instead of Pack.whatever(w,
1908# ...), with pack(), place() and grid() being short for
1909# pack_configure(), place_configure() and grid_columnconfigure(), and
1910# forget() being short for pack_forget(). As a practical matter, I'm
1911# afraid that there is too much code out there that may be using the
1912# Pack, Place or Grid class, so I leave them intact -- but only as
1913# backwards compatibility features. Also note that those methods that
1914# take a master as argument (e.g. pack_propagate) have been moved to
1915# the Misc class (which now incorporates all methods common between
1916# toplevel and interior widgets). Again, for compatibility, these are
1917# copied into the Pack, Place or Grid class.
1918
1919
1920def Tcl(screenName=None, baseName=None, className='Tk', useTk=0):
1921 return Tk(screenName, baseName, className, useTk)
1922
1923class Pack:
1924 """Geometry manager Pack.
1925
1926 Base class to use the methods pack_* in every widget."""
1927 def pack_configure(self, cnf={}, **kw):
1928 """Pack a widget in the parent widget. Use as options:
1929 after=widget - pack it after you have packed widget
1930 anchor=NSEW (or subset) - position widget according to
1931 given direction
Georg Brandl7943a322008-05-29 07:18:49 +00001932 before=widget - pack it before you will pack widget
Georg Brandl33cece02008-05-20 06:58:21 +00001933 expand=bool - expand widget if parent size grows
1934 fill=NONE or X or Y or BOTH - fill widget if widget grows
1935 in=master - use master to contain this widget
Georg Brandl7943a322008-05-29 07:18:49 +00001936 in_=master - see 'in' option description
Georg Brandl33cece02008-05-20 06:58:21 +00001937 ipadx=amount - add internal padding in x direction
1938 ipady=amount - add internal padding in y direction
1939 padx=amount - add padding in x direction
1940 pady=amount - add padding in y direction
1941 side=TOP or BOTTOM or LEFT or RIGHT - where to add this widget.
1942 """
1943 self.tk.call(
1944 ('pack', 'configure', self._w)
1945 + self._options(cnf, kw))
1946 pack = configure = config = pack_configure
1947 def pack_forget(self):
1948 """Unmap this widget and do not use it for the packing order."""
1949 self.tk.call('pack', 'forget', self._w)
1950 forget = pack_forget
1951 def pack_info(self):
1952 """Return information about the packing options
1953 for this widget."""
Serhiy Storchakaceaf6822014-09-06 22:47:02 +03001954 d = _splitdict(self.tk, self.tk.call('pack', 'info', self._w))
1955 if 'in' in d:
1956 d['in'] = self.nametowidget(d['in'])
1957 return d
Georg Brandl33cece02008-05-20 06:58:21 +00001958 info = pack_info
1959 propagate = pack_propagate = Misc.pack_propagate
1960 slaves = pack_slaves = Misc.pack_slaves
1961
1962class Place:
1963 """Geometry manager Place.
1964
1965 Base class to use the methods place_* in every widget."""
1966 def place_configure(self, cnf={}, **kw):
1967 """Place a widget in the parent widget. Use as options:
Georg Brandl7943a322008-05-29 07:18:49 +00001968 in=master - master relative to which the widget is placed
1969 in_=master - see 'in' option description
Georg Brandl33cece02008-05-20 06:58:21 +00001970 x=amount - locate anchor of this widget at position x of master
1971 y=amount - locate anchor of this widget at position y of master
1972 relx=amount - locate anchor of this widget between 0.0 and 1.0
1973 relative to width of master (1.0 is right edge)
Georg Brandl7943a322008-05-29 07:18:49 +00001974 rely=amount - locate anchor of this widget between 0.0 and 1.0
Georg Brandl33cece02008-05-20 06:58:21 +00001975 relative to height of master (1.0 is bottom edge)
Georg Brandl7943a322008-05-29 07:18:49 +00001976 anchor=NSEW (or subset) - position anchor according to given direction
Georg Brandl33cece02008-05-20 06:58:21 +00001977 width=amount - width of this widget in pixel
1978 height=amount - height of this widget in pixel
1979 relwidth=amount - width of this widget between 0.0 and 1.0
1980 relative to width of master (1.0 is the same width
Georg Brandl7943a322008-05-29 07:18:49 +00001981 as the master)
1982 relheight=amount - height of this widget between 0.0 and 1.0
Georg Brandl33cece02008-05-20 06:58:21 +00001983 relative to height of master (1.0 is the same
Georg Brandl7943a322008-05-29 07:18:49 +00001984 height as the master)
1985 bordermode="inside" or "outside" - whether to take border width of
1986 master widget into account
1987 """
Georg Brandl33cece02008-05-20 06:58:21 +00001988 self.tk.call(
1989 ('place', 'configure', self._w)
1990 + self._options(cnf, kw))
1991 place = configure = config = place_configure
1992 def place_forget(self):
1993 """Unmap this widget."""
1994 self.tk.call('place', 'forget', self._w)
1995 forget = place_forget
1996 def place_info(self):
1997 """Return information about the placing options
1998 for this widget."""
Serhiy Storchakaceaf6822014-09-06 22:47:02 +03001999 d = _splitdict(self.tk, self.tk.call('place', 'info', self._w))
2000 if 'in' in d:
2001 d['in'] = self.nametowidget(d['in'])
2002 return d
Georg Brandl33cece02008-05-20 06:58:21 +00002003 info = place_info
2004 slaves = place_slaves = Misc.place_slaves
2005
2006class Grid:
2007 """Geometry manager Grid.
2008
2009 Base class to use the methods grid_* in every widget."""
2010 # Thanks to Masazumi Yoshikawa (yosikawa@isi.edu)
2011 def grid_configure(self, cnf={}, **kw):
2012 """Position a widget in the parent widget in a grid. Use as options:
2013 column=number - use cell identified with given column (starting with 0)
2014 columnspan=number - this widget will span several columns
2015 in=master - use master to contain this widget
Georg Brandl7943a322008-05-29 07:18:49 +00002016 in_=master - see 'in' option description
Georg Brandl33cece02008-05-20 06:58:21 +00002017 ipadx=amount - add internal padding in x direction
2018 ipady=amount - add internal padding in y direction
2019 padx=amount - add padding in x direction
2020 pady=amount - add padding in y direction
2021 row=number - use cell identified with given row (starting with 0)
2022 rowspan=number - this widget will span several rows
2023 sticky=NSEW - if cell is larger on which sides will this
2024 widget stick to the cell boundary
2025 """
2026 self.tk.call(
2027 ('grid', 'configure', self._w)
2028 + self._options(cnf, kw))
2029 grid = configure = config = grid_configure
2030 bbox = grid_bbox = Misc.grid_bbox
2031 columnconfigure = grid_columnconfigure = Misc.grid_columnconfigure
2032 def grid_forget(self):
2033 """Unmap this widget."""
2034 self.tk.call('grid', 'forget', self._w)
2035 forget = grid_forget
2036 def grid_remove(self):
2037 """Unmap this widget but remember the grid options."""
2038 self.tk.call('grid', 'remove', self._w)
2039 def grid_info(self):
2040 """Return information about the options
2041 for positioning this widget in a grid."""
Serhiy Storchakaceaf6822014-09-06 22:47:02 +03002042 d = _splitdict(self.tk, self.tk.call('grid', 'info', self._w))
2043 if 'in' in d:
2044 d['in'] = self.nametowidget(d['in'])
2045 return d
Georg Brandl33cece02008-05-20 06:58:21 +00002046 info = grid_info
2047 location = grid_location = Misc.grid_location
2048 propagate = grid_propagate = Misc.grid_propagate
2049 rowconfigure = grid_rowconfigure = Misc.grid_rowconfigure
2050 size = grid_size = Misc.grid_size
2051 slaves = grid_slaves = Misc.grid_slaves
2052
2053class BaseWidget(Misc):
2054 """Internal class."""
2055 def _setup(self, master, cnf):
2056 """Internal function. Sets up information about children."""
2057 if _support_default_root:
2058 global _default_root
2059 if not master:
2060 if not _default_root:
2061 _default_root = Tk()
2062 master = _default_root
2063 self.master = master
2064 self.tk = master.tk
2065 name = None
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +00002066 if 'name' in cnf:
Georg Brandl33cece02008-05-20 06:58:21 +00002067 name = cnf['name']
2068 del cnf['name']
2069 if not name:
2070 name = repr(id(self))
2071 self._name = name
2072 if master._w=='.':
2073 self._w = '.' + name
2074 else:
2075 self._w = master._w + '.' + name
2076 self.children = {}
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +00002077 if self._name in self.master.children:
Georg Brandl33cece02008-05-20 06:58:21 +00002078 self.master.children[self._name].destroy()
2079 self.master.children[self._name] = self
2080 def __init__(self, master, widgetName, cnf={}, kw={}, extra=()):
2081 """Construct a widget with the parent widget MASTER, a name WIDGETNAME
2082 and appropriate options."""
2083 if kw:
2084 cnf = _cnfmerge((cnf, kw))
2085 self.widgetName = widgetName
2086 BaseWidget._setup(self, master, cnf)
Hirokazu Yamamotob9828f62008-11-03 18:03:06 +00002087 if self._tclCommands is None:
2088 self._tclCommands = []
Georg Brandl33cece02008-05-20 06:58:21 +00002089 classes = []
2090 for k in cnf.keys():
2091 if type(k) is ClassType:
2092 classes.append((k, cnf[k]))
2093 del cnf[k]
2094 self.tk.call(
2095 (widgetName, self._w) + extra + self._options(cnf))
2096 for k, v in classes:
2097 k.configure(self, v)
2098 def destroy(self):
2099 """Destroy this and all descendants widgets."""
2100 for c in self.children.values(): c.destroy()
2101 self.tk.call('destroy', self._w)
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +00002102 if self._name in self.master.children:
Georg Brandl33cece02008-05-20 06:58:21 +00002103 del self.master.children[self._name]
2104 Misc.destroy(self)
2105 def _do(self, name, args=()):
2106 # XXX Obsolete -- better use self.tk.call directly!
2107 return self.tk.call((self._w, name) + args)
2108
2109class Widget(BaseWidget, Pack, Place, Grid):
2110 """Internal class.
2111
2112 Base class for a widget which can be positioned with the geometry managers
2113 Pack, Place or Grid."""
2114 pass
2115
2116class Toplevel(BaseWidget, Wm):
2117 """Toplevel widget, e.g. for dialogs."""
2118 def __init__(self, master=None, cnf={}, **kw):
2119 """Construct a toplevel widget with the parent MASTER.
2120
2121 Valid resource names: background, bd, bg, borderwidth, class,
2122 colormap, container, cursor, height, highlightbackground,
2123 highlightcolor, highlightthickness, menu, relief, screen, takefocus,
2124 use, visual, width."""
2125 if kw:
2126 cnf = _cnfmerge((cnf, kw))
2127 extra = ()
2128 for wmkey in ['screen', 'class_', 'class', 'visual',
2129 'colormap']:
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +00002130 if wmkey in cnf:
Georg Brandl33cece02008-05-20 06:58:21 +00002131 val = cnf[wmkey]
2132 # TBD: a hack needed because some keys
2133 # are not valid as keyword arguments
2134 if wmkey[-1] == '_': opt = '-'+wmkey[:-1]
2135 else: opt = '-'+wmkey
2136 extra = extra + (opt, val)
2137 del cnf[wmkey]
2138 BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra)
2139 root = self._root()
2140 self.iconname(root.iconname())
2141 self.title(root.title())
2142 self.protocol("WM_DELETE_WINDOW", self.destroy)
2143
2144class Button(Widget):
2145 """Button widget."""
2146 def __init__(self, master=None, cnf={}, **kw):
2147 """Construct a button widget with the parent MASTER.
2148
2149 STANDARD OPTIONS
2150
2151 activebackground, activeforeground, anchor,
2152 background, bitmap, borderwidth, cursor,
2153 disabledforeground, font, foreground
2154 highlightbackground, highlightcolor,
2155 highlightthickness, image, justify,
2156 padx, pady, relief, repeatdelay,
2157 repeatinterval, takefocus, text,
2158 textvariable, underline, wraplength
2159
2160 WIDGET-SPECIFIC OPTIONS
2161
2162 command, compound, default, height,
2163 overrelief, state, width
2164 """
2165 Widget.__init__(self, master, 'button', cnf, kw)
2166
2167 def tkButtonEnter(self, *dummy):
2168 self.tk.call('tkButtonEnter', self._w)
2169
2170 def tkButtonLeave(self, *dummy):
2171 self.tk.call('tkButtonLeave', self._w)
2172
2173 def tkButtonDown(self, *dummy):
2174 self.tk.call('tkButtonDown', self._w)
2175
2176 def tkButtonUp(self, *dummy):
2177 self.tk.call('tkButtonUp', self._w)
2178
2179 def tkButtonInvoke(self, *dummy):
2180 self.tk.call('tkButtonInvoke', self._w)
2181
2182 def flash(self):
2183 """Flash the button.
2184
2185 This is accomplished by redisplaying
2186 the button several times, alternating between active and
2187 normal colors. At the end of the flash the button is left
2188 in the same normal/active state as when the command was
2189 invoked. This command is ignored if the button's state is
2190 disabled.
2191 """
2192 self.tk.call(self._w, 'flash')
2193
2194 def invoke(self):
2195 """Invoke the command associated with the button.
2196
2197 The return value is the return value from the command,
2198 or an empty string if there is no command associated with
2199 the button. This command is ignored if the button's state
2200 is disabled.
2201 """
2202 return self.tk.call(self._w, 'invoke')
2203
2204# Indices:
2205# XXX I don't like these -- take them away
2206def AtEnd():
2207 return 'end'
2208def AtInsert(*args):
2209 s = 'insert'
2210 for a in args:
2211 if a: s = s + (' ' + a)
2212 return s
2213def AtSelFirst():
2214 return 'sel.first'
2215def AtSelLast():
2216 return 'sel.last'
2217def At(x, y=None):
2218 if y is None:
2219 return '@%r' % (x,)
2220 else:
2221 return '@%r,%r' % (x, y)
2222
Guilherme Poloe45f0172009-08-14 14:36:45 +00002223class Canvas(Widget, XView, YView):
Georg Brandl33cece02008-05-20 06:58:21 +00002224 """Canvas widget to display graphical elements like lines or text."""
2225 def __init__(self, master=None, cnf={}, **kw):
2226 """Construct a canvas widget with the parent MASTER.
2227
2228 Valid resource names: background, bd, bg, borderwidth, closeenough,
2229 confine, cursor, height, highlightbackground, highlightcolor,
2230 highlightthickness, insertbackground, insertborderwidth,
2231 insertofftime, insertontime, insertwidth, offset, relief,
2232 scrollregion, selectbackground, selectborderwidth, selectforeground,
2233 state, takefocus, width, xscrollcommand, xscrollincrement,
2234 yscrollcommand, yscrollincrement."""
2235 Widget.__init__(self, master, 'canvas', cnf, kw)
2236 def addtag(self, *args):
2237 """Internal function."""
2238 self.tk.call((self._w, 'addtag') + args)
2239 def addtag_above(self, newtag, tagOrId):
2240 """Add tag NEWTAG to all items above TAGORID."""
2241 self.addtag(newtag, 'above', tagOrId)
2242 def addtag_all(self, newtag):
2243 """Add tag NEWTAG to all items."""
2244 self.addtag(newtag, 'all')
2245 def addtag_below(self, newtag, tagOrId):
2246 """Add tag NEWTAG to all items below TAGORID."""
2247 self.addtag(newtag, 'below', tagOrId)
2248 def addtag_closest(self, newtag, x, y, halo=None, start=None):
2249 """Add tag NEWTAG to item which is closest to pixel at X, Y.
2250 If several match take the top-most.
2251 All items closer than HALO are considered overlapping (all are
2252 closests). If START is specified the next below this tag is taken."""
2253 self.addtag(newtag, 'closest', x, y, halo, start)
2254 def addtag_enclosed(self, newtag, x1, y1, x2, y2):
2255 """Add tag NEWTAG to all items in the rectangle defined
2256 by X1,Y1,X2,Y2."""
2257 self.addtag(newtag, 'enclosed', x1, y1, x2, y2)
2258 def addtag_overlapping(self, newtag, x1, y1, x2, y2):
2259 """Add tag NEWTAG to all items which overlap the rectangle
2260 defined by X1,Y1,X2,Y2."""
2261 self.addtag(newtag, 'overlapping', x1, y1, x2, y2)
2262 def addtag_withtag(self, newtag, tagOrId):
2263 """Add tag NEWTAG to all items with TAGORID."""
2264 self.addtag(newtag, 'withtag', tagOrId)
2265 def bbox(self, *args):
2266 """Return a tuple of X1,Y1,X2,Y2 coordinates for a rectangle
2267 which encloses all items with tags specified as arguments."""
2268 return self._getints(
2269 self.tk.call((self._w, 'bbox') + args)) or None
2270 def tag_unbind(self, tagOrId, sequence, funcid=None):
2271 """Unbind for all items with TAGORID for event SEQUENCE the
2272 function identified with FUNCID."""
2273 self.tk.call(self._w, 'bind', tagOrId, sequence, '')
2274 if funcid:
2275 self.deletecommand(funcid)
2276 def tag_bind(self, tagOrId, sequence=None, func=None, add=None):
2277 """Bind to all items with TAGORID at event SEQUENCE a call to function FUNC.
2278
2279 An additional boolean parameter ADD specifies whether FUNC will be
2280 called additionally to the other bound function or whether it will
2281 replace the previous function. See bind for the return value."""
2282 return self._bind((self._w, 'bind', tagOrId),
2283 sequence, func, add)
2284 def canvasx(self, screenx, gridspacing=None):
2285 """Return the canvas x coordinate of pixel position SCREENX rounded
2286 to nearest multiple of GRIDSPACING units."""
2287 return getdouble(self.tk.call(
2288 self._w, 'canvasx', screenx, gridspacing))
2289 def canvasy(self, screeny, gridspacing=None):
2290 """Return the canvas y coordinate of pixel position SCREENY rounded
2291 to nearest multiple of GRIDSPACING units."""
2292 return getdouble(self.tk.call(
2293 self._w, 'canvasy', screeny, gridspacing))
2294 def coords(self, *args):
2295 """Return a list of coordinates for the item given in ARGS."""
2296 # XXX Should use _flatten on args
2297 return map(getdouble,
2298 self.tk.splitlist(
2299 self.tk.call((self._w, 'coords') + args)))
2300 def _create(self, itemType, args, kw): # Args: (val, val, ..., cnf={})
2301 """Internal function."""
2302 args = _flatten(args)
2303 cnf = args[-1]
2304 if type(cnf) in (DictionaryType, TupleType):
2305 args = args[:-1]
2306 else:
2307 cnf = {}
2308 return getint(self.tk.call(
2309 self._w, 'create', itemType,
2310 *(args + self._options(cnf, kw))))
2311 def create_arc(self, *args, **kw):
2312 """Create arc shaped region with coordinates x1,y1,x2,y2."""
2313 return self._create('arc', args, kw)
2314 def create_bitmap(self, *args, **kw):
2315 """Create bitmap with coordinates x1,y1."""
2316 return self._create('bitmap', args, kw)
2317 def create_image(self, *args, **kw):
2318 """Create image item with coordinates x1,y1."""
2319 return self._create('image', args, kw)
2320 def create_line(self, *args, **kw):
2321 """Create line with coordinates x1,y1,...,xn,yn."""
2322 return self._create('line', args, kw)
2323 def create_oval(self, *args, **kw):
2324 """Create oval with coordinates x1,y1,x2,y2."""
2325 return self._create('oval', args, kw)
2326 def create_polygon(self, *args, **kw):
2327 """Create polygon with coordinates x1,y1,...,xn,yn."""
2328 return self._create('polygon', args, kw)
2329 def create_rectangle(self, *args, **kw):
2330 """Create rectangle with coordinates x1,y1,x2,y2."""
2331 return self._create('rectangle', args, kw)
2332 def create_text(self, *args, **kw):
2333 """Create text with coordinates x1,y1."""
2334 return self._create('text', args, kw)
2335 def create_window(self, *args, **kw):
2336 """Create window with coordinates x1,y1,x2,y2."""
2337 return self._create('window', args, kw)
2338 def dchars(self, *args):
2339 """Delete characters of text items identified by tag or id in ARGS (possibly
2340 several times) from FIRST to LAST character (including)."""
2341 self.tk.call((self._w, 'dchars') + args)
2342 def delete(self, *args):
2343 """Delete items identified by all tag or ids contained in ARGS."""
2344 self.tk.call((self._w, 'delete') + args)
2345 def dtag(self, *args):
2346 """Delete tag or id given as last arguments in ARGS from items
2347 identified by first argument in ARGS."""
2348 self.tk.call((self._w, 'dtag') + args)
2349 def find(self, *args):
2350 """Internal function."""
2351 return self._getints(
2352 self.tk.call((self._w, 'find') + args)) or ()
2353 def find_above(self, tagOrId):
2354 """Return items above TAGORID."""
2355 return self.find('above', tagOrId)
2356 def find_all(self):
2357 """Return all items."""
2358 return self.find('all')
2359 def find_below(self, tagOrId):
2360 """Return all items below TAGORID."""
2361 return self.find('below', tagOrId)
2362 def find_closest(self, x, y, halo=None, start=None):
2363 """Return item which is closest to pixel at X, Y.
2364 If several match take the top-most.
2365 All items closer than HALO are considered overlapping (all are
Vijay Kumarf31f2252017-05-23 11:46:27 +05302366 closest). If START is specified the next below this tag is taken."""
Georg Brandl33cece02008-05-20 06:58:21 +00002367 return self.find('closest', x, y, halo, start)
2368 def find_enclosed(self, x1, y1, x2, y2):
2369 """Return all items in rectangle defined
2370 by X1,Y1,X2,Y2."""
2371 return self.find('enclosed', x1, y1, x2, y2)
2372 def find_overlapping(self, x1, y1, x2, y2):
2373 """Return all items which overlap the rectangle
2374 defined by X1,Y1,X2,Y2."""
2375 return self.find('overlapping', x1, y1, x2, y2)
2376 def find_withtag(self, tagOrId):
2377 """Return all items with TAGORID."""
2378 return self.find('withtag', tagOrId)
2379 def focus(self, *args):
2380 """Set focus to the first item specified in ARGS."""
2381 return self.tk.call((self._w, 'focus') + args)
2382 def gettags(self, *args):
2383 """Return tags associated with the first item specified in ARGS."""
2384 return self.tk.splitlist(
2385 self.tk.call((self._w, 'gettags') + args))
2386 def icursor(self, *args):
2387 """Set cursor at position POS in the item identified by TAGORID.
2388 In ARGS TAGORID must be first."""
2389 self.tk.call((self._w, 'icursor') + args)
2390 def index(self, *args):
2391 """Return position of cursor as integer in item specified in ARGS."""
2392 return getint(self.tk.call((self._w, 'index') + args))
2393 def insert(self, *args):
2394 """Insert TEXT in item TAGORID at position POS. ARGS must
2395 be TAGORID POS TEXT."""
2396 self.tk.call((self._w, 'insert') + args)
2397 def itemcget(self, tagOrId, option):
2398 """Return the resource value for an OPTION for item TAGORID."""
2399 return self.tk.call(
2400 (self._w, 'itemcget') + (tagOrId, '-'+option))
2401 def itemconfigure(self, tagOrId, cnf=None, **kw):
2402 """Configure resources of an item TAGORID.
2403
2404 The values for resources are specified as keyword
2405 arguments. To get an overview about
2406 the allowed keyword arguments call the method without arguments.
2407 """
2408 return self._configure(('itemconfigure', tagOrId), cnf, kw)
2409 itemconfig = itemconfigure
2410 # lower, tkraise/lift hide Misc.lower, Misc.tkraise/lift,
2411 # so the preferred name for them is tag_lower, tag_raise
2412 # (similar to tag_bind, and similar to the Text widget);
2413 # unfortunately can't delete the old ones yet (maybe in 1.6)
2414 def tag_lower(self, *args):
2415 """Lower an item TAGORID given in ARGS
2416 (optional below another item)."""
2417 self.tk.call((self._w, 'lower') + args)
2418 lower = tag_lower
2419 def move(self, *args):
2420 """Move an item TAGORID given in ARGS."""
2421 self.tk.call((self._w, 'move') + args)
2422 def postscript(self, cnf={}, **kw):
2423 """Print the contents of the canvas to a postscript
2424 file. Valid options: colormap, colormode, file, fontmap,
2425 height, pageanchor, pageheight, pagewidth, pagex, pagey,
Vijay Kumarf31f2252017-05-23 11:46:27 +05302426 rotate, width, x, y."""
Georg Brandl33cece02008-05-20 06:58:21 +00002427 return self.tk.call((self._w, 'postscript') +
2428 self._options(cnf, kw))
2429 def tag_raise(self, *args):
2430 """Raise an item TAGORID given in ARGS
2431 (optional above another item)."""
2432 self.tk.call((self._w, 'raise') + args)
2433 lift = tkraise = tag_raise
2434 def scale(self, *args):
2435 """Scale item TAGORID with XORIGIN, YORIGIN, XSCALE, YSCALE."""
2436 self.tk.call((self._w, 'scale') + args)
2437 def scan_mark(self, x, y):
2438 """Remember the current X, Y coordinates."""
2439 self.tk.call(self._w, 'scan', 'mark', x, y)
2440 def scan_dragto(self, x, y, gain=10):
2441 """Adjust the view of the canvas to GAIN times the
2442 difference between X and Y and the coordinates given in
2443 scan_mark."""
2444 self.tk.call(self._w, 'scan', 'dragto', x, y, gain)
2445 def select_adjust(self, tagOrId, index):
2446 """Adjust the end of the selection near the cursor of an item TAGORID to index."""
2447 self.tk.call(self._w, 'select', 'adjust', tagOrId, index)
2448 def select_clear(self):
2449 """Clear the selection if it is in this widget."""
2450 self.tk.call(self._w, 'select', 'clear')
2451 def select_from(self, tagOrId, index):
2452 """Set the fixed end of a selection in item TAGORID to INDEX."""
2453 self.tk.call(self._w, 'select', 'from', tagOrId, index)
2454 def select_item(self):
2455 """Return the item which has the selection."""
2456 return self.tk.call(self._w, 'select', 'item') or None
2457 def select_to(self, tagOrId, index):
2458 """Set the variable end of a selection in item TAGORID to INDEX."""
2459 self.tk.call(self._w, 'select', 'to', tagOrId, index)
2460 def type(self, tagOrId):
2461 """Return the type of the item TAGORID."""
2462 return self.tk.call(self._w, 'type', tagOrId) or None
Georg Brandl33cece02008-05-20 06:58:21 +00002463
2464class Checkbutton(Widget):
2465 """Checkbutton widget which is either in on- or off-state."""
2466 def __init__(self, master=None, cnf={}, **kw):
2467 """Construct a checkbutton widget with the parent MASTER.
2468
2469 Valid resource names: activebackground, activeforeground, anchor,
2470 background, bd, bg, bitmap, borderwidth, command, cursor,
2471 disabledforeground, fg, font, foreground, height,
2472 highlightbackground, highlightcolor, highlightthickness, image,
2473 indicatoron, justify, offvalue, onvalue, padx, pady, relief,
2474 selectcolor, selectimage, state, takefocus, text, textvariable,
2475 underline, variable, width, wraplength."""
2476 Widget.__init__(self, master, 'checkbutton', cnf, kw)
2477 def deselect(self):
2478 """Put the button in off-state."""
2479 self.tk.call(self._w, 'deselect')
2480 def flash(self):
2481 """Flash the button."""
2482 self.tk.call(self._w, 'flash')
2483 def invoke(self):
2484 """Toggle the button and invoke a command if given as resource."""
2485 return self.tk.call(self._w, 'invoke')
2486 def select(self):
2487 """Put the button in on-state."""
2488 self.tk.call(self._w, 'select')
2489 def toggle(self):
2490 """Toggle the button."""
2491 self.tk.call(self._w, 'toggle')
2492
Guilherme Poloe45f0172009-08-14 14:36:45 +00002493class Entry(Widget, XView):
Martin Panter53ae0ba2016-02-10 05:44:01 +00002494 """Entry widget which allows displaying simple text."""
Georg Brandl33cece02008-05-20 06:58:21 +00002495 def __init__(self, master=None, cnf={}, **kw):
2496 """Construct an entry widget with the parent MASTER.
2497
2498 Valid resource names: background, bd, bg, borderwidth, cursor,
2499 exportselection, fg, font, foreground, highlightbackground,
2500 highlightcolor, highlightthickness, insertbackground,
2501 insertborderwidth, insertofftime, insertontime, insertwidth,
2502 invalidcommand, invcmd, justify, relief, selectbackground,
2503 selectborderwidth, selectforeground, show, state, takefocus,
2504 textvariable, validate, validatecommand, vcmd, width,
2505 xscrollcommand."""
2506 Widget.__init__(self, master, 'entry', cnf, kw)
2507 def delete(self, first, last=None):
2508 """Delete text from FIRST to LAST (not included)."""
2509 self.tk.call(self._w, 'delete', first, last)
2510 def get(self):
2511 """Return the text."""
2512 return self.tk.call(self._w, 'get')
2513 def icursor(self, index):
2514 """Insert cursor at INDEX."""
2515 self.tk.call(self._w, 'icursor', index)
2516 def index(self, index):
2517 """Return position of cursor."""
2518 return getint(self.tk.call(
2519 self._w, 'index', index))
2520 def insert(self, index, string):
2521 """Insert STRING at INDEX."""
2522 self.tk.call(self._w, 'insert', index, string)
2523 def scan_mark(self, x):
2524 """Remember the current X, Y coordinates."""
2525 self.tk.call(self._w, 'scan', 'mark', x)
2526 def scan_dragto(self, x):
2527 """Adjust the view of the canvas to 10 times the
2528 difference between X and Y and the coordinates given in
2529 scan_mark."""
2530 self.tk.call(self._w, 'scan', 'dragto', x)
2531 def selection_adjust(self, index):
2532 """Adjust the end of the selection near the cursor to INDEX."""
2533 self.tk.call(self._w, 'selection', 'adjust', index)
2534 select_adjust = selection_adjust
2535 def selection_clear(self):
2536 """Clear the selection if it is in this widget."""
2537 self.tk.call(self._w, 'selection', 'clear')
2538 select_clear = selection_clear
2539 def selection_from(self, index):
2540 """Set the fixed end of a selection to INDEX."""
2541 self.tk.call(self._w, 'selection', 'from', index)
2542 select_from = selection_from
2543 def selection_present(self):
Guilherme Polo75e1f992009-08-14 14:43:43 +00002544 """Return True if there are characters selected in the entry, False
2545 otherwise."""
Georg Brandl33cece02008-05-20 06:58:21 +00002546 return self.tk.getboolean(
2547 self.tk.call(self._w, 'selection', 'present'))
2548 select_present = selection_present
2549 def selection_range(self, start, end):
2550 """Set the selection from START to END (not included)."""
2551 self.tk.call(self._w, 'selection', 'range', start, end)
2552 select_range = selection_range
2553 def selection_to(self, index):
2554 """Set the variable end of a selection to INDEX."""
2555 self.tk.call(self._w, 'selection', 'to', index)
2556 select_to = selection_to
Georg Brandl33cece02008-05-20 06:58:21 +00002557
2558class Frame(Widget):
2559 """Frame widget which may contain other widgets and can have a 3D border."""
2560 def __init__(self, master=None, cnf={}, **kw):
2561 """Construct a frame widget with the parent MASTER.
2562
2563 Valid resource names: background, bd, bg, borderwidth, class,
2564 colormap, container, cursor, height, highlightbackground,
2565 highlightcolor, highlightthickness, relief, takefocus, visual, width."""
2566 cnf = _cnfmerge((cnf, kw))
2567 extra = ()
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +00002568 if 'class_' in cnf:
Georg Brandl33cece02008-05-20 06:58:21 +00002569 extra = ('-class', cnf['class_'])
2570 del cnf['class_']
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +00002571 elif 'class' in cnf:
Georg Brandl33cece02008-05-20 06:58:21 +00002572 extra = ('-class', cnf['class'])
2573 del cnf['class']
2574 Widget.__init__(self, master, 'frame', cnf, {}, extra)
2575
2576class Label(Widget):
2577 """Label widget which can display text and bitmaps."""
2578 def __init__(self, master=None, cnf={}, **kw):
2579 """Construct a label widget with the parent MASTER.
2580
2581 STANDARD OPTIONS
2582
2583 activebackground, activeforeground, anchor,
2584 background, bitmap, borderwidth, cursor,
2585 disabledforeground, font, foreground,
2586 highlightbackground, highlightcolor,
2587 highlightthickness, image, justify,
2588 padx, pady, relief, takefocus, text,
2589 textvariable, underline, wraplength
2590
2591 WIDGET-SPECIFIC OPTIONS
2592
2593 height, state, width
2594
2595 """
2596 Widget.__init__(self, master, 'label', cnf, kw)
2597
Guilherme Poloe45f0172009-08-14 14:36:45 +00002598class Listbox(Widget, XView, YView):
Georg Brandl33cece02008-05-20 06:58:21 +00002599 """Listbox widget which can display a list of strings."""
2600 def __init__(self, master=None, cnf={}, **kw):
2601 """Construct a listbox widget with the parent MASTER.
2602
2603 Valid resource names: background, bd, bg, borderwidth, cursor,
2604 exportselection, fg, font, foreground, height, highlightbackground,
2605 highlightcolor, highlightthickness, relief, selectbackground,
2606 selectborderwidth, selectforeground, selectmode, setgrid, takefocus,
2607 width, xscrollcommand, yscrollcommand, listvariable."""
2608 Widget.__init__(self, master, 'listbox', cnf, kw)
2609 def activate(self, index):
2610 """Activate item identified by INDEX."""
2611 self.tk.call(self._w, 'activate', index)
Serhiy Storchakaf94686f2014-06-02 21:30:53 +03002612 def bbox(self, index):
Georg Brandl33cece02008-05-20 06:58:21 +00002613 """Return a tuple of X1,Y1,X2,Y2 coordinates for a rectangle
Serhiy Storchakaf94686f2014-06-02 21:30:53 +03002614 which encloses the item identified by the given index."""
2615 return self._getints(self.tk.call(self._w, 'bbox', index)) or None
Georg Brandl33cece02008-05-20 06:58:21 +00002616 def curselection(self):
Serhiy Storchakaf94686f2014-06-02 21:30:53 +03002617 """Return the indices of currently selected item."""
2618 return self._getints(self.tk.call(self._w, 'curselection')) or ()
Georg Brandl33cece02008-05-20 06:58:21 +00002619 def delete(self, first, last=None):
Serhiy Storchaka417367a2014-06-02 16:50:03 +03002620 """Delete items from FIRST to LAST (included)."""
Georg Brandl33cece02008-05-20 06:58:21 +00002621 self.tk.call(self._w, 'delete', first, last)
2622 def get(self, first, last=None):
Serhiy Storchaka417367a2014-06-02 16:50:03 +03002623 """Get list of items from FIRST to LAST (included)."""
Serhiy Storchakaf94686f2014-06-02 21:30:53 +03002624 if last is not None:
Georg Brandl33cece02008-05-20 06:58:21 +00002625 return self.tk.splitlist(self.tk.call(
2626 self._w, 'get', first, last))
2627 else:
2628 return self.tk.call(self._w, 'get', first)
2629 def index(self, index):
2630 """Return index of item identified with INDEX."""
2631 i = self.tk.call(self._w, 'index', index)
2632 if i == 'none': return None
2633 return getint(i)
2634 def insert(self, index, *elements):
2635 """Insert ELEMENTS at INDEX."""
2636 self.tk.call((self._w, 'insert', index) + elements)
2637 def nearest(self, y):
2638 """Get index of item which is nearest to y coordinate Y."""
2639 return getint(self.tk.call(
2640 self._w, 'nearest', y))
2641 def scan_mark(self, x, y):
2642 """Remember the current X, Y coordinates."""
2643 self.tk.call(self._w, 'scan', 'mark', x, y)
2644 def scan_dragto(self, x, y):
2645 """Adjust the view of the listbox to 10 times the
2646 difference between X and Y and the coordinates given in
2647 scan_mark."""
2648 self.tk.call(self._w, 'scan', 'dragto', x, y)
2649 def see(self, index):
2650 """Scroll such that INDEX is visible."""
2651 self.tk.call(self._w, 'see', index)
2652 def selection_anchor(self, index):
2653 """Set the fixed end oft the selection to INDEX."""
2654 self.tk.call(self._w, 'selection', 'anchor', index)
2655 select_anchor = selection_anchor
2656 def selection_clear(self, first, last=None):
Serhiy Storchaka417367a2014-06-02 16:50:03 +03002657 """Clear the selection from FIRST to LAST (included)."""
Georg Brandl33cece02008-05-20 06:58:21 +00002658 self.tk.call(self._w,
2659 'selection', 'clear', first, last)
2660 select_clear = selection_clear
2661 def selection_includes(self, index):
2662 """Return 1 if INDEX is part of the selection."""
2663 return self.tk.getboolean(self.tk.call(
2664 self._w, 'selection', 'includes', index))
2665 select_includes = selection_includes
2666 def selection_set(self, first, last=None):
Serhiy Storchaka417367a2014-06-02 16:50:03 +03002667 """Set the selection from FIRST to LAST (included) without
Georg Brandl33cece02008-05-20 06:58:21 +00002668 changing the currently selected elements."""
2669 self.tk.call(self._w, 'selection', 'set', first, last)
2670 select_set = selection_set
2671 def size(self):
2672 """Return the number of elements in the listbox."""
2673 return getint(self.tk.call(self._w, 'size'))
Georg Brandl33cece02008-05-20 06:58:21 +00002674 def itemcget(self, index, option):
2675 """Return the resource value for an ITEM and an OPTION."""
2676 return self.tk.call(
2677 (self._w, 'itemcget') + (index, '-'+option))
2678 def itemconfigure(self, index, cnf=None, **kw):
2679 """Configure resources of an ITEM.
2680
2681 The values for resources are specified as keyword arguments.
2682 To get an overview about the allowed keyword arguments
2683 call the method without arguments.
2684 Valid resource names: background, bg, foreground, fg,
2685 selectbackground, selectforeground."""
2686 return self._configure(('itemconfigure', index), cnf, kw)
2687 itemconfig = itemconfigure
2688
2689class Menu(Widget):
Martin Panter53ae0ba2016-02-10 05:44:01 +00002690 """Menu widget which allows displaying menu bars, pull-down menus and pop-up menus."""
Georg Brandl33cece02008-05-20 06:58:21 +00002691 def __init__(self, master=None, cnf={}, **kw):
2692 """Construct menu widget with the parent MASTER.
2693
2694 Valid resource names: activebackground, activeborderwidth,
2695 activeforeground, background, bd, bg, borderwidth, cursor,
2696 disabledforeground, fg, font, foreground, postcommand, relief,
2697 selectcolor, takefocus, tearoff, tearoffcommand, title, type."""
2698 Widget.__init__(self, master, 'menu', cnf, kw)
2699 def tk_bindForTraversal(self):
Serhiy Storchaka2ce9ddd2014-07-25 12:23:08 +03002700 # obsolete since Tk 4.0
2701 import warnings
2702 warnings.warn('tk_bindForTraversal() does nothing and '
2703 'will be removed in 3.6',
2704 DeprecationWarning, stacklevel=2)
Georg Brandl33cece02008-05-20 06:58:21 +00002705 def tk_mbPost(self):
2706 self.tk.call('tk_mbPost', self._w)
2707 def tk_mbUnpost(self):
2708 self.tk.call('tk_mbUnpost')
2709 def tk_traverseToMenu(self, char):
2710 self.tk.call('tk_traverseToMenu', self._w, char)
2711 def tk_traverseWithinMenu(self, char):
2712 self.tk.call('tk_traverseWithinMenu', self._w, char)
2713 def tk_getMenuButtons(self):
2714 return self.tk.call('tk_getMenuButtons', self._w)
2715 def tk_nextMenu(self, count):
2716 self.tk.call('tk_nextMenu', count)
2717 def tk_nextMenuEntry(self, count):
2718 self.tk.call('tk_nextMenuEntry', count)
2719 def tk_invokeMenu(self):
2720 self.tk.call('tk_invokeMenu', self._w)
2721 def tk_firstMenu(self):
2722 self.tk.call('tk_firstMenu', self._w)
2723 def tk_mbButtonDown(self):
2724 self.tk.call('tk_mbButtonDown', self._w)
2725 def tk_popup(self, x, y, entry=""):
2726 """Post the menu at position X,Y with entry ENTRY."""
2727 self.tk.call('tk_popup', self._w, x, y, entry)
2728 def activate(self, index):
2729 """Activate entry at INDEX."""
2730 self.tk.call(self._w, 'activate', index)
2731 def add(self, itemType, cnf={}, **kw):
2732 """Internal function."""
2733 self.tk.call((self._w, 'add', itemType) +
2734 self._options(cnf, kw))
2735 def add_cascade(self, cnf={}, **kw):
2736 """Add hierarchical menu item."""
2737 self.add('cascade', cnf or kw)
2738 def add_checkbutton(self, cnf={}, **kw):
2739 """Add checkbutton menu item."""
2740 self.add('checkbutton', cnf or kw)
2741 def add_command(self, cnf={}, **kw):
2742 """Add command menu item."""
2743 self.add('command', cnf or kw)
2744 def add_radiobutton(self, cnf={}, **kw):
2745 """Addd radio menu item."""
2746 self.add('radiobutton', cnf or kw)
2747 def add_separator(self, cnf={}, **kw):
2748 """Add separator."""
2749 self.add('separator', cnf or kw)
2750 def insert(self, index, itemType, cnf={}, **kw):
2751 """Internal function."""
2752 self.tk.call((self._w, 'insert', index, itemType) +
2753 self._options(cnf, kw))
2754 def insert_cascade(self, index, cnf={}, **kw):
2755 """Add hierarchical menu item at INDEX."""
2756 self.insert(index, 'cascade', cnf or kw)
2757 def insert_checkbutton(self, index, cnf={}, **kw):
2758 """Add checkbutton menu item at INDEX."""
2759 self.insert(index, 'checkbutton', cnf or kw)
2760 def insert_command(self, index, cnf={}, **kw):
2761 """Add command menu item at INDEX."""
2762 self.insert(index, 'command', cnf or kw)
2763 def insert_radiobutton(self, index, cnf={}, **kw):
2764 """Addd radio menu item at INDEX."""
2765 self.insert(index, 'radiobutton', cnf or kw)
2766 def insert_separator(self, index, cnf={}, **kw):
2767 """Add separator at INDEX."""
2768 self.insert(index, 'separator', cnf or kw)
2769 def delete(self, index1, index2=None):
Hirokazu Yamamotob9828f62008-11-03 18:03:06 +00002770 """Delete menu items between INDEX1 and INDEX2 (included)."""
Robert Schuppenies14646332008-08-10 11:01:53 +00002771 if index2 is None:
2772 index2 = index1
Hirokazu Yamamotob9828f62008-11-03 18:03:06 +00002773
2774 num_index1, num_index2 = self.index(index1), self.index(index2)
2775 if (num_index1 is None) or (num_index2 is None):
2776 num_index1, num_index2 = 0, -1
2777
2778 for i in range(num_index1, num_index2 + 1):
2779 if 'command' in self.entryconfig(i):
2780 c = str(self.entrycget(i, 'command'))
2781 if c:
2782 self.deletecommand(c)
Georg Brandl33cece02008-05-20 06:58:21 +00002783 self.tk.call(self._w, 'delete', index1, index2)
Georg Brandl33cece02008-05-20 06:58:21 +00002784 def entrycget(self, index, option):
Serhiy Storchaka9a118f12016-04-17 09:37:36 +03002785 """Return the resource value of a menu item for OPTION at INDEX."""
Georg Brandl33cece02008-05-20 06:58:21 +00002786 return self.tk.call(self._w, 'entrycget', index, '-' + option)
2787 def entryconfigure(self, index, cnf=None, **kw):
2788 """Configure a menu item at INDEX."""
2789 return self._configure(('entryconfigure', index), cnf, kw)
2790 entryconfig = entryconfigure
2791 def index(self, index):
2792 """Return the index of a menu item identified by INDEX."""
2793 i = self.tk.call(self._w, 'index', index)
2794 if i == 'none': return None
2795 return getint(i)
2796 def invoke(self, index):
2797 """Invoke a menu item identified by INDEX and execute
2798 the associated command."""
2799 return self.tk.call(self._w, 'invoke', index)
2800 def post(self, x, y):
2801 """Display a menu at position X,Y."""
2802 self.tk.call(self._w, 'post', x, y)
2803 def type(self, index):
2804 """Return the type of the menu item at INDEX."""
2805 return self.tk.call(self._w, 'type', index)
2806 def unpost(self):
2807 """Unmap a menu."""
2808 self.tk.call(self._w, 'unpost')
2809 def yposition(self, index):
2810 """Return the y-position of the topmost pixel of the menu item at INDEX."""
2811 return getint(self.tk.call(
2812 self._w, 'yposition', index))
2813
2814class Menubutton(Widget):
2815 """Menubutton widget, obsolete since Tk8.0."""
2816 def __init__(self, master=None, cnf={}, **kw):
2817 Widget.__init__(self, master, 'menubutton', cnf, kw)
2818
2819class Message(Widget):
2820 """Message widget to display multiline text. Obsolete since Label does it too."""
2821 def __init__(self, master=None, cnf={}, **kw):
2822 Widget.__init__(self, master, 'message', cnf, kw)
2823
2824class Radiobutton(Widget):
2825 """Radiobutton widget which shows only one of several buttons in on-state."""
2826 def __init__(self, master=None, cnf={}, **kw):
2827 """Construct a radiobutton widget with the parent MASTER.
2828
2829 Valid resource names: activebackground, activeforeground, anchor,
2830 background, bd, bg, bitmap, borderwidth, command, cursor,
2831 disabledforeground, fg, font, foreground, height,
2832 highlightbackground, highlightcolor, highlightthickness, image,
2833 indicatoron, justify, padx, pady, relief, selectcolor, selectimage,
2834 state, takefocus, text, textvariable, underline, value, variable,
2835 width, wraplength."""
2836 Widget.__init__(self, master, 'radiobutton', cnf, kw)
2837 def deselect(self):
2838 """Put the button in off-state."""
2839
2840 self.tk.call(self._w, 'deselect')
2841 def flash(self):
2842 """Flash the button."""
2843 self.tk.call(self._w, 'flash')
2844 def invoke(self):
2845 """Toggle the button and invoke a command if given as resource."""
2846 return self.tk.call(self._w, 'invoke')
2847 def select(self):
2848 """Put the button in on-state."""
2849 self.tk.call(self._w, 'select')
2850
2851class Scale(Widget):
2852 """Scale widget which can display a numerical scale."""
2853 def __init__(self, master=None, cnf={}, **kw):
2854 """Construct a scale widget with the parent MASTER.
2855
2856 Valid resource names: activebackground, background, bigincrement, bd,
2857 bg, borderwidth, command, cursor, digits, fg, font, foreground, from,
2858 highlightbackground, highlightcolor, highlightthickness, label,
2859 length, orient, relief, repeatdelay, repeatinterval, resolution,
2860 showvalue, sliderlength, sliderrelief, state, takefocus,
2861 tickinterval, to, troughcolor, variable, width."""
2862 Widget.__init__(self, master, 'scale', cnf, kw)
2863 def get(self):
2864 """Get the current value as integer or float."""
2865 value = self.tk.call(self._w, 'get')
2866 try:
2867 return getint(value)
2868 except ValueError:
2869 return getdouble(value)
2870 def set(self, value):
2871 """Set the value to VALUE."""
2872 self.tk.call(self._w, 'set', value)
2873 def coords(self, value=None):
2874 """Return a tuple (X,Y) of the point along the centerline of the
2875 trough that corresponds to VALUE or the current value if None is
2876 given."""
2877
2878 return self._getints(self.tk.call(self._w, 'coords', value))
2879 def identify(self, x, y):
2880 """Return where the point X,Y lies. Valid return values are "slider",
2881 "though1" and "though2"."""
2882 return self.tk.call(self._w, 'identify', x, y)
2883
2884class Scrollbar(Widget):
2885 """Scrollbar widget which displays a slider at a certain position."""
2886 def __init__(self, master=None, cnf={}, **kw):
2887 """Construct a scrollbar widget with the parent MASTER.
2888
2889 Valid resource names: activebackground, activerelief,
2890 background, bd, bg, borderwidth, command, cursor,
2891 elementborderwidth, highlightbackground,
2892 highlightcolor, highlightthickness, jump, orient,
2893 relief, repeatdelay, repeatinterval, takefocus,
2894 troughcolor, width."""
2895 Widget.__init__(self, master, 'scrollbar', cnf, kw)
2896 def activate(self, index):
2897 """Display the element at INDEX with activebackground and activerelief.
2898 INDEX can be "arrow1","slider" or "arrow2"."""
2899 self.tk.call(self._w, 'activate', index)
2900 def delta(self, deltax, deltay):
2901 """Return the fractional change of the scrollbar setting if it
2902 would be moved by DELTAX or DELTAY pixels."""
2903 return getdouble(
2904 self.tk.call(self._w, 'delta', deltax, deltay))
2905 def fraction(self, x, y):
2906 """Return the fractional value which corresponds to a slider
2907 position of X,Y."""
2908 return getdouble(self.tk.call(self._w, 'fraction', x, y))
2909 def identify(self, x, y):
2910 """Return the element under position X,Y as one of
2911 "arrow1","slider","arrow2" or ""."""
2912 return self.tk.call(self._w, 'identify', x, y)
2913 def get(self):
2914 """Return the current fractional values (upper and lower end)
2915 of the slider position."""
2916 return self._getdoubles(self.tk.call(self._w, 'get'))
2917 def set(self, *args):
2918 """Set the fractional values of the slider position (upper and
2919 lower ends as value between 0 and 1)."""
2920 self.tk.call((self._w, 'set') + args)
2921
2922
2923
Guilherme Poloe45f0172009-08-14 14:36:45 +00002924class Text(Widget, XView, YView):
Georg Brandl33cece02008-05-20 06:58:21 +00002925 """Text widget which can display text in various forms."""
2926 def __init__(self, master=None, cnf={}, **kw):
2927 """Construct a text widget with the parent MASTER.
2928
2929 STANDARD OPTIONS
2930
2931 background, borderwidth, cursor,
2932 exportselection, font, foreground,
2933 highlightbackground, highlightcolor,
2934 highlightthickness, insertbackground,
2935 insertborderwidth, insertofftime,
2936 insertontime, insertwidth, padx, pady,
2937 relief, selectbackground,
2938 selectborderwidth, selectforeground,
2939 setgrid, takefocus,
2940 xscrollcommand, yscrollcommand,
2941
2942 WIDGET-SPECIFIC OPTIONS
2943
2944 autoseparators, height, maxundo,
2945 spacing1, spacing2, spacing3,
2946 state, tabs, undo, width, wrap,
2947
2948 """
2949 Widget.__init__(self, master, 'text', cnf, kw)
2950 def bbox(self, *args):
2951 """Return a tuple of (x,y,width,height) which gives the bounding
2952 box of the visible part of the character at the index in ARGS."""
2953 return self._getints(
2954 self.tk.call((self._w, 'bbox') + args)) or None
2955 def tk_textSelectTo(self, index):
2956 self.tk.call('tk_textSelectTo', self._w, index)
2957 def tk_textBackspace(self):
2958 self.tk.call('tk_textBackspace', self._w)
2959 def tk_textIndexCloser(self, a, b, c):
2960 self.tk.call('tk_textIndexCloser', self._w, a, b, c)
2961 def tk_textResetAnchor(self, index):
2962 self.tk.call('tk_textResetAnchor', self._w, index)
2963 def compare(self, index1, op, index2):
2964 """Return whether between index INDEX1 and index INDEX2 the
2965 relation OP is satisfied. OP is one of <, <=, ==, >=, >, or !=."""
2966 return self.tk.getboolean(self.tk.call(
2967 self._w, 'compare', index1, op, index2))
2968 def debug(self, boolean=None):
2969 """Turn on the internal consistency checks of the B-Tree inside the text
2970 widget according to BOOLEAN."""
Serhiy Storchaka31b9c842013-11-03 14:28:29 +02002971 if boolean is None:
Serhiy Storchaka2bca9de2014-01-11 13:12:58 +02002972 return self.tk.getboolean(self.tk.call(self._w, 'debug'))
Serhiy Storchaka31b9c842013-11-03 14:28:29 +02002973 self.tk.call(self._w, 'debug', boolean)
Georg Brandl33cece02008-05-20 06:58:21 +00002974 def delete(self, index1, index2=None):
2975 """Delete the characters between INDEX1 and INDEX2 (not included)."""
2976 self.tk.call(self._w, 'delete', index1, index2)
2977 def dlineinfo(self, index):
2978 """Return tuple (x,y,width,height,baseline) giving the bounding box
2979 and baseline position of the visible part of the line containing
2980 the character at INDEX."""
2981 return self._getints(self.tk.call(self._w, 'dlineinfo', index))
2982 def dump(self, index1, index2=None, command=None, **kw):
2983 """Return the contents of the widget between index1 and index2.
2984
2985 The type of contents returned in filtered based on the keyword
2986 parameters; if 'all', 'image', 'mark', 'tag', 'text', or 'window' are
2987 given and true, then the corresponding items are returned. The result
2988 is a list of triples of the form (key, value, index). If none of the
2989 keywords are true then 'all' is used by default.
2990
2991 If the 'command' argument is given, it is called once for each element
2992 of the list of triples, with the values of each triple serving as the
2993 arguments to the function. In this case the list is not returned."""
2994 args = []
2995 func_name = None
2996 result = None
2997 if not command:
2998 # Never call the dump command without the -command flag, since the
2999 # output could involve Tcl quoting and would be a pain to parse
3000 # right. Instead just set the command to build a list of triples
3001 # as if we had done the parsing.
3002 result = []
3003 def append_triple(key, value, index, result=result):
3004 result.append((key, value, index))
3005 command = append_triple
3006 try:
3007 if not isinstance(command, str):
3008 func_name = command = self._register(command)
3009 args += ["-command", command]
3010 for key in kw:
3011 if kw[key]: args.append("-" + key)
3012 args.append(index1)
3013 if index2:
3014 args.append(index2)
3015 self.tk.call(self._w, "dump", *args)
3016 return result
3017 finally:
3018 if func_name:
3019 self.deletecommand(func_name)
3020
3021 ## new in tk8.4
3022 def edit(self, *args):
3023 """Internal method
3024
3025 This method controls the undo mechanism and
3026 the modified flag. The exact behavior of the
3027 command depends on the option argument that
3028 follows the edit argument. The following forms
3029 of the command are currently supported:
3030
3031 edit_modified, edit_redo, edit_reset, edit_separator
3032 and edit_undo
3033
3034 """
3035 return self.tk.call(self._w, 'edit', *args)
3036
3037 def edit_modified(self, arg=None):
3038 """Get or Set the modified flag
3039
3040 If arg is not specified, returns the modified
3041 flag of the widget. The insert, delete, edit undo and
3042 edit redo commands or the user can set or clear the
3043 modified flag. If boolean is specified, sets the
3044 modified flag of the widget to arg.
3045 """
3046 return self.edit("modified", arg)
3047
3048 def edit_redo(self):
3049 """Redo the last undone edit
3050
3051 When the undo option is true, reapplies the last
3052 undone edits provided no other edits were done since
3053 then. Generates an error when the redo stack is empty.
3054 Does nothing when the undo option is false.
3055 """
3056 return self.edit("redo")
3057
3058 def edit_reset(self):
3059 """Clears the undo and redo stacks
3060 """
3061 return self.edit("reset")
3062
3063 def edit_separator(self):
3064 """Inserts a separator (boundary) on the undo stack.
3065
3066 Does nothing when the undo option is false
3067 """
3068 return self.edit("separator")
3069
3070 def edit_undo(self):
3071 """Undoes the last edit action
3072
3073 If the undo option is true. An edit action is defined
3074 as all the insert and delete commands that are recorded
3075 on the undo stack in between two separators. Generates
3076 an error when the undo stack is empty. Does nothing
3077 when the undo option is false
3078 """
3079 return self.edit("undo")
3080
3081 def get(self, index1, index2=None):
3082 """Return the text from INDEX1 to INDEX2 (not included)."""
3083 return self.tk.call(self._w, 'get', index1, index2)
3084 # (Image commands are new in 8.0)
3085 def image_cget(self, index, option):
3086 """Return the value of OPTION of an embedded image at INDEX."""
3087 if option[:1] != "-":
3088 option = "-" + option
3089 if option[-1:] == "_":
3090 option = option[:-1]
3091 return self.tk.call(self._w, "image", "cget", index, option)
3092 def image_configure(self, index, cnf=None, **kw):
3093 """Configure an embedded image at INDEX."""
3094 return self._configure(('image', 'configure', index), cnf, kw)
3095 def image_create(self, index, cnf={}, **kw):
3096 """Create an embedded image at INDEX."""
3097 return self.tk.call(
3098 self._w, "image", "create", index,
3099 *self._options(cnf, kw))
3100 def image_names(self):
3101 """Return all names of embedded images in this widget."""
3102 return self.tk.call(self._w, "image", "names")
3103 def index(self, index):
3104 """Return the index in the form line.char for INDEX."""
3105 return str(self.tk.call(self._w, 'index', index))
3106 def insert(self, index, chars, *args):
3107 """Insert CHARS before the characters at INDEX. An additional
3108 tag can be given in ARGS. Additional CHARS and tags can follow in ARGS."""
3109 self.tk.call((self._w, 'insert', index, chars) + args)
3110 def mark_gravity(self, markName, direction=None):
3111 """Change the gravity of a mark MARKNAME to DIRECTION (LEFT or RIGHT).
3112 Return the current value if None is given for DIRECTION."""
3113 return self.tk.call(
3114 (self._w, 'mark', 'gravity', markName, direction))
3115 def mark_names(self):
3116 """Return all mark names."""
3117 return self.tk.splitlist(self.tk.call(
3118 self._w, 'mark', 'names'))
3119 def mark_set(self, markName, index):
3120 """Set mark MARKNAME before the character at INDEX."""
3121 self.tk.call(self._w, 'mark', 'set', markName, index)
3122 def mark_unset(self, *markNames):
3123 """Delete all marks in MARKNAMES."""
3124 self.tk.call((self._w, 'mark', 'unset') + markNames)
3125 def mark_next(self, index):
3126 """Return the name of the next mark after INDEX."""
3127 return self.tk.call(self._w, 'mark', 'next', index) or None
3128 def mark_previous(self, index):
3129 """Return the name of the previous mark before INDEX."""
3130 return self.tk.call(self._w, 'mark', 'previous', index) or None
3131 def scan_mark(self, x, y):
3132 """Remember the current X, Y coordinates."""
3133 self.tk.call(self._w, 'scan', 'mark', x, y)
3134 def scan_dragto(self, x, y):
3135 """Adjust the view of the text to 10 times the
3136 difference between X and Y and the coordinates given in
3137 scan_mark."""
3138 self.tk.call(self._w, 'scan', 'dragto', x, y)
3139 def search(self, pattern, index, stopindex=None,
3140 forwards=None, backwards=None, exact=None,
3141 regexp=None, nocase=None, count=None, elide=None):
3142 """Search PATTERN beginning from INDEX until STOPINDEX.
Guilherme Polod2ea0332009-02-09 16:41:09 +00003143 Return the index of the first character of a match or an
3144 empty string."""
Georg Brandl33cece02008-05-20 06:58:21 +00003145 args = [self._w, 'search']
3146 if forwards: args.append('-forwards')
3147 if backwards: args.append('-backwards')
3148 if exact: args.append('-exact')
3149 if regexp: args.append('-regexp')
3150 if nocase: args.append('-nocase')
3151 if elide: args.append('-elide')
3152 if count: args.append('-count'); args.append(count)
Guilherme Polod2ea0332009-02-09 16:41:09 +00003153 if pattern and pattern[0] == '-': args.append('--')
Georg Brandl33cece02008-05-20 06:58:21 +00003154 args.append(pattern)
3155 args.append(index)
3156 if stopindex: args.append(stopindex)
Guilherme Polo6d6c1fd2009-03-07 01:19:12 +00003157 return str(self.tk.call(tuple(args)))
Georg Brandl33cece02008-05-20 06:58:21 +00003158 def see(self, index):
3159 """Scroll such that the character at INDEX is visible."""
3160 self.tk.call(self._w, 'see', index)
3161 def tag_add(self, tagName, index1, *args):
3162 """Add tag TAGNAME to all characters between INDEX1 and index2 in ARGS.
3163 Additional pairs of indices may follow in ARGS."""
3164 self.tk.call(
3165 (self._w, 'tag', 'add', tagName, index1) + args)
3166 def tag_unbind(self, tagName, sequence, funcid=None):
3167 """Unbind for all characters with TAGNAME for event SEQUENCE the
3168 function identified with FUNCID."""
3169 self.tk.call(self._w, 'tag', 'bind', tagName, sequence, '')
3170 if funcid:
3171 self.deletecommand(funcid)
3172 def tag_bind(self, tagName, sequence, func, add=None):
3173 """Bind to all characters with TAGNAME at event SEQUENCE a call to function FUNC.
3174
3175 An additional boolean parameter ADD specifies whether FUNC will be
3176 called additionally to the other bound function or whether it will
3177 replace the previous function. See bind for the return value."""
3178 return self._bind((self._w, 'tag', 'bind', tagName),
3179 sequence, func, add)
3180 def tag_cget(self, tagName, option):
3181 """Return the value of OPTION for tag TAGNAME."""
3182 if option[:1] != '-':
3183 option = '-' + option
3184 if option[-1:] == '_':
3185 option = option[:-1]
3186 return self.tk.call(self._w, 'tag', 'cget', tagName, option)
3187 def tag_configure(self, tagName, cnf=None, **kw):
3188 """Configure a tag TAGNAME."""
3189 return self._configure(('tag', 'configure', tagName), cnf, kw)
3190 tag_config = tag_configure
3191 def tag_delete(self, *tagNames):
3192 """Delete all tags in TAGNAMES."""
3193 self.tk.call((self._w, 'tag', 'delete') + tagNames)
3194 def tag_lower(self, tagName, belowThis=None):
3195 """Change the priority of tag TAGNAME such that it is lower
3196 than the priority of BELOWTHIS."""
3197 self.tk.call(self._w, 'tag', 'lower', tagName, belowThis)
3198 def tag_names(self, index=None):
3199 """Return a list of all tag names."""
3200 return self.tk.splitlist(
3201 self.tk.call(self._w, 'tag', 'names', index))
3202 def tag_nextrange(self, tagName, index1, index2=None):
3203 """Return a list of start and end index for the first sequence of
3204 characters between INDEX1 and INDEX2 which all have tag TAGNAME.
3205 The text is searched forward from INDEX1."""
3206 return self.tk.splitlist(self.tk.call(
3207 self._w, 'tag', 'nextrange', tagName, index1, index2))
3208 def tag_prevrange(self, tagName, index1, index2=None):
3209 """Return a list of start and end index for the first sequence of
3210 characters between INDEX1 and INDEX2 which all have tag TAGNAME.
3211 The text is searched backwards from INDEX1."""
3212 return self.tk.splitlist(self.tk.call(
3213 self._w, 'tag', 'prevrange', tagName, index1, index2))
3214 def tag_raise(self, tagName, aboveThis=None):
3215 """Change the priority of tag TAGNAME such that it is higher
3216 than the priority of ABOVETHIS."""
3217 self.tk.call(
3218 self._w, 'tag', 'raise', tagName, aboveThis)
3219 def tag_ranges(self, tagName):
3220 """Return a list of ranges of text which have tag TAGNAME."""
3221 return self.tk.splitlist(self.tk.call(
3222 self._w, 'tag', 'ranges', tagName))
3223 def tag_remove(self, tagName, index1, index2=None):
3224 """Remove tag TAGNAME from all characters between INDEX1 and INDEX2."""
3225 self.tk.call(
3226 self._w, 'tag', 'remove', tagName, index1, index2)
3227 def window_cget(self, index, option):
3228 """Return the value of OPTION of an embedded window at INDEX."""
3229 if option[:1] != '-':
3230 option = '-' + option
3231 if option[-1:] == '_':
3232 option = option[:-1]
3233 return self.tk.call(self._w, 'window', 'cget', index, option)
3234 def window_configure(self, index, cnf=None, **kw):
3235 """Configure an embedded window at INDEX."""
3236 return self._configure(('window', 'configure', index), cnf, kw)
3237 window_config = window_configure
3238 def window_create(self, index, cnf={}, **kw):
3239 """Create a window at INDEX."""
3240 self.tk.call(
3241 (self._w, 'window', 'create', index)
3242 + self._options(cnf, kw))
3243 def window_names(self):
3244 """Return all names of embedded windows in this widget."""
3245 return self.tk.splitlist(
3246 self.tk.call(self._w, 'window', 'names'))
Georg Brandl33cece02008-05-20 06:58:21 +00003247 def yview_pickplace(self, *what):
3248 """Obsolete function, use see."""
3249 self.tk.call((self._w, 'yview', '-pickplace') + what)
3250
3251
3252class _setit:
3253 """Internal class. It wraps the command in the widget OptionMenu."""
3254 def __init__(self, var, value, callback=None):
3255 self.__value = value
3256 self.__var = var
3257 self.__callback = callback
3258 def __call__(self, *args):
3259 self.__var.set(self.__value)
3260 if self.__callback:
3261 self.__callback(self.__value, *args)
3262
3263class OptionMenu(Menubutton):
3264 """OptionMenu which allows the user to select a value from a menu."""
3265 def __init__(self, master, variable, value, *values, **kwargs):
3266 """Construct an optionmenu widget with the parent MASTER, with
3267 the resource textvariable set to VARIABLE, the initially selected
3268 value VALUE, the other menu values VALUES and an additional
3269 keyword argument command."""
3270 kw = {"borderwidth": 2, "textvariable": variable,
3271 "indicatoron": 1, "relief": RAISED, "anchor": "c",
3272 "highlightthickness": 2}
3273 Widget.__init__(self, master, "menubutton", kw)
3274 self.widgetName = 'tk_optionMenu'
3275 menu = self.__menu = Menu(self, name="menu", tearoff=0)
3276 self.menuname = menu._w
3277 # 'command' is the only supported keyword
3278 callback = kwargs.get('command')
Benjamin Peterson6e3dbbd2009-10-09 22:15:50 +00003279 if 'command' in kwargs:
Georg Brandl33cece02008-05-20 06:58:21 +00003280 del kwargs['command']
3281 if kwargs:
3282 raise TclError, 'unknown option -'+kwargs.keys()[0]
3283 menu.add_command(label=value,
3284 command=_setit(variable, value, callback))
3285 for v in values:
3286 menu.add_command(label=v,
3287 command=_setit(variable, v, callback))
3288 self["menu"] = menu
3289
3290 def __getitem__(self, name):
3291 if name == 'menu':
3292 return self.__menu
3293 return Widget.__getitem__(self, name)
3294
3295 def destroy(self):
3296 """Destroy this widget and the associated menu."""
3297 Menubutton.destroy(self)
3298 self.__menu = None
3299
3300class Image:
3301 """Base class for images."""
3302 _last_id = 0
3303 def __init__(self, imgtype, name=None, cnf={}, master=None, **kw):
3304 self.name = None
3305 if not master:
3306 master = _default_root
3307 if not master:
3308 raise RuntimeError, 'Too early to create image'
Serhiy Storchakad3ea0652014-08-24 09:07:09 +03003309 self.tk = getattr(master, 'tk', master)
Georg Brandl33cece02008-05-20 06:58:21 +00003310 if not name:
3311 Image._last_id += 1
3312 name = "pyimage%r" % (Image._last_id,) # tk itself would use image<x>
3313 # The following is needed for systems where id(x)
3314 # can return a negative number, such as Linux/m68k:
3315 if name[0] == '-': name = '_' + name[1:]
3316 if kw and cnf: cnf = _cnfmerge((cnf, kw))
3317 elif kw: cnf = kw
3318 options = ()
3319 for k, v in cnf.items():
Benjamin Petersonde055992009-10-09 22:05:45 +00003320 if hasattr(v, '__call__'):
Georg Brandl33cece02008-05-20 06:58:21 +00003321 v = self._register(v)
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003322 elif k in ('data', 'maskdata'):
3323 v = self.tk._createbytearray(v)
Georg Brandl33cece02008-05-20 06:58:21 +00003324 options = options + ('-'+k, v)
3325 self.tk.call(('image', 'create', imgtype, name,) + options)
3326 self.name = name
3327 def __str__(self): return self.name
3328 def __del__(self):
3329 if self.name:
3330 try:
3331 self.tk.call('image', 'delete', self.name)
3332 except TclError:
3333 # May happen if the root was destroyed
3334 pass
3335 def __setitem__(self, key, value):
3336 self.tk.call(self.name, 'configure', '-'+key, value)
3337 def __getitem__(self, key):
3338 return self.tk.call(self.name, 'configure', '-'+key)
3339 def configure(self, **kw):
3340 """Configure the image."""
3341 res = ()
3342 for k, v in _cnfmerge(kw).items():
3343 if v is not None:
3344 if k[-1] == '_': k = k[:-1]
Benjamin Petersonde055992009-10-09 22:05:45 +00003345 if hasattr(v, '__call__'):
Georg Brandl33cece02008-05-20 06:58:21 +00003346 v = self._register(v)
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003347 elif k in ('data', 'maskdata'):
3348 v = self.tk._createbytearray(v)
Georg Brandl33cece02008-05-20 06:58:21 +00003349 res = res + ('-'+k, v)
3350 self.tk.call((self.name, 'config') + res)
3351 config = configure
3352 def height(self):
3353 """Return the height of the image."""
3354 return getint(
3355 self.tk.call('image', 'height', self.name))
3356 def type(self):
Vijay Kumarf31f2252017-05-23 11:46:27 +05303357 """Return the type of the image, e.g. "photo" or "bitmap"."""
Georg Brandl33cece02008-05-20 06:58:21 +00003358 return self.tk.call('image', 'type', self.name)
3359 def width(self):
3360 """Return the width of the image."""
3361 return getint(
3362 self.tk.call('image', 'width', self.name))
3363
3364class PhotoImage(Image):
3365 """Widget which can display colored images in GIF, PPM/PGM format."""
3366 def __init__(self, name=None, cnf={}, master=None, **kw):
3367 """Create an image with NAME.
3368
3369 Valid resource names: data, format, file, gamma, height, palette,
3370 width."""
3371 Image.__init__(self, 'photo', name, cnf, master, **kw)
3372 def blank(self):
3373 """Display a transparent image."""
3374 self.tk.call(self.name, 'blank')
3375 def cget(self, option):
3376 """Return the value of OPTION."""
3377 return self.tk.call(self.name, 'cget', '-' + option)
3378 # XXX config
3379 def __getitem__(self, key):
3380 return self.tk.call(self.name, 'cget', '-' + key)
3381 # XXX copy -from, -to, ...?
3382 def copy(self):
3383 """Return a new PhotoImage with the same image as this widget."""
Serhiy Storchakad3ea0652014-08-24 09:07:09 +03003384 destImage = PhotoImage(master=self.tk)
Georg Brandl33cece02008-05-20 06:58:21 +00003385 self.tk.call(destImage, 'copy', self.name)
3386 return destImage
Terry Jan Reedyca761002016-03-11 15:30:27 -05003387 def zoom(self, x, y=''):
Georg Brandl33cece02008-05-20 06:58:21 +00003388 """Return a new PhotoImage with the same image as this widget
Terry Jan Reedyca761002016-03-11 15:30:27 -05003389 but zoom it with a factor of x in the X direction and y in the Y
3390 direction. If y is not given, the default value is the same as x.
3391 """
Serhiy Storchakad3ea0652014-08-24 09:07:09 +03003392 destImage = PhotoImage(master=self.tk)
Georg Brandl33cece02008-05-20 06:58:21 +00003393 if y=='': y=x
3394 self.tk.call(destImage, 'copy', self.name, '-zoom',x,y)
3395 return destImage
Terry Jan Reedyca761002016-03-11 15:30:27 -05003396 def subsample(self, x, y=''):
Georg Brandl33cece02008-05-20 06:58:21 +00003397 """Return a new PhotoImage based on the same image as this widget
Terry Jan Reedyca761002016-03-11 15:30:27 -05003398 but use only every Xth or Yth pixel. If y is not given, the
3399 default value is the same as x.
3400 """
Serhiy Storchakad3ea0652014-08-24 09:07:09 +03003401 destImage = PhotoImage(master=self.tk)
Georg Brandl33cece02008-05-20 06:58:21 +00003402 if y=='': y=x
3403 self.tk.call(destImage, 'copy', self.name, '-subsample',x,y)
3404 return destImage
3405 def get(self, x, y):
3406 """Return the color (red, green, blue) of the pixel at X,Y."""
3407 return self.tk.call(self.name, 'get', x, y)
3408 def put(self, data, to=None):
Mark Dickinson3e4caeb2009-02-21 20:27:01 +00003409 """Put row formatted colors to image starting from
Georg Brandl33cece02008-05-20 06:58:21 +00003410 position TO, e.g. image.put("{red green} {blue yellow}", to=(4,6))"""
3411 args = (self.name, 'put', data)
3412 if to:
3413 if to[0] == '-to':
3414 to = to[1:]
3415 args = args + ('-to',) + tuple(to)
3416 self.tk.call(args)
3417 # XXX read
3418 def write(self, filename, format=None, from_coords=None):
3419 """Write image to file FILENAME in FORMAT starting from
3420 position FROM_COORDS."""
3421 args = (self.name, 'write', filename)
3422 if format:
3423 args = args + ('-format', format)
3424 if from_coords:
3425 args = args + ('-from',) + tuple(from_coords)
3426 self.tk.call(args)
3427
3428class BitmapImage(Image):
3429 """Widget which can display a bitmap."""
3430 def __init__(self, name=None, cnf={}, master=None, **kw):
3431 """Create a bitmap with NAME.
3432
3433 Valid resource names: background, data, file, foreground, maskdata, maskfile."""
3434 Image.__init__(self, 'bitmap', name, cnf, master, **kw)
3435
Serhiy Storchaka9be238d2014-01-07 19:32:58 +02003436def image_names():
3437 return _default_root.tk.splitlist(_default_root.tk.call('image', 'names'))
3438
3439def image_types():
3440 return _default_root.tk.splitlist(_default_root.tk.call('image', 'types'))
Georg Brandl33cece02008-05-20 06:58:21 +00003441
3442
Guilherme Poloe45f0172009-08-14 14:36:45 +00003443class Spinbox(Widget, XView):
Georg Brandl33cece02008-05-20 06:58:21 +00003444 """spinbox widget."""
3445 def __init__(self, master=None, cnf={}, **kw):
3446 """Construct a spinbox widget with the parent MASTER.
3447
3448 STANDARD OPTIONS
3449
3450 activebackground, background, borderwidth,
3451 cursor, exportselection, font, foreground,
3452 highlightbackground, highlightcolor,
3453 highlightthickness, insertbackground,
3454 insertborderwidth, insertofftime,
3455 insertontime, insertwidth, justify, relief,
3456 repeatdelay, repeatinterval,
3457 selectbackground, selectborderwidth
3458 selectforeground, takefocus, textvariable
3459 xscrollcommand.
3460
3461 WIDGET-SPECIFIC OPTIONS
3462
3463 buttonbackground, buttoncursor,
3464 buttondownrelief, buttonuprelief,
3465 command, disabledbackground,
3466 disabledforeground, format, from,
3467 invalidcommand, increment,
3468 readonlybackground, state, to,
3469 validate, validatecommand values,
3470 width, wrap,
3471 """
3472 Widget.__init__(self, master, 'spinbox', cnf, kw)
3473
3474 def bbox(self, index):
3475 """Return a tuple of X1,Y1,X2,Y2 coordinates for a
3476 rectangle which encloses the character given by index.
3477
3478 The first two elements of the list give the x and y
3479 coordinates of the upper-left corner of the screen
3480 area covered by the character (in pixels relative
3481 to the widget) and the last two elements give the
3482 width and height of the character, in pixels. The
3483 bounding box may refer to a region outside the
3484 visible area of the window.
3485 """
Serhiy Storchaka8630f162013-11-03 14:13:08 +02003486 return self._getints(self.tk.call(self._w, 'bbox', index)) or None
Georg Brandl33cece02008-05-20 06:58:21 +00003487
3488 def delete(self, first, last=None):
3489 """Delete one or more elements of the spinbox.
3490
3491 First is the index of the first character to delete,
3492 and last is the index of the character just after
3493 the last one to delete. If last isn't specified it
3494 defaults to first+1, i.e. a single character is
3495 deleted. This command returns an empty string.
3496 """
3497 return self.tk.call(self._w, 'delete', first, last)
3498
3499 def get(self):
3500 """Returns the spinbox's string"""
3501 return self.tk.call(self._w, 'get')
3502
3503 def icursor(self, index):
3504 """Alter the position of the insertion cursor.
3505
3506 The insertion cursor will be displayed just before
3507 the character given by index. Returns an empty string
3508 """
3509 return self.tk.call(self._w, 'icursor', index)
3510
3511 def identify(self, x, y):
3512 """Returns the name of the widget at position x, y
3513
3514 Return value is one of: none, buttondown, buttonup, entry
3515 """
3516 return self.tk.call(self._w, 'identify', x, y)
3517
3518 def index(self, index):
3519 """Returns the numerical index corresponding to index
3520 """
3521 return self.tk.call(self._w, 'index', index)
3522
3523 def insert(self, index, s):
3524 """Insert string s at index
3525
3526 Returns an empty string.
3527 """
3528 return self.tk.call(self._w, 'insert', index, s)
3529
3530 def invoke(self, element):
3531 """Causes the specified element to be invoked
3532
3533 The element could be buttondown or buttonup
3534 triggering the action associated with it.
3535 """
3536 return self.tk.call(self._w, 'invoke', element)
3537
3538 def scan(self, *args):
3539 """Internal function."""
3540 return self._getints(
3541 self.tk.call((self._w, 'scan') + args)) or ()
3542
3543 def scan_mark(self, x):
3544 """Records x and the current view in the spinbox window;
3545
3546 used in conjunction with later scan dragto commands.
3547 Typically this command is associated with a mouse button
3548 press in the widget. It returns an empty string.
3549 """
3550 return self.scan("mark", x)
3551
3552 def scan_dragto(self, x):
3553 """Compute the difference between the given x argument
3554 and the x argument to the last scan mark command
3555
3556 It then adjusts the view left or right by 10 times the
3557 difference in x-coordinates. This command is typically
3558 associated with mouse motion events in the widget, to
3559 produce the effect of dragging the spinbox at high speed
3560 through the window. The return value is an empty string.
3561 """
3562 return self.scan("dragto", x)
3563
3564 def selection(self, *args):
3565 """Internal function."""
3566 return self._getints(
3567 self.tk.call((self._w, 'selection') + args)) or ()
3568
3569 def selection_adjust(self, index):
3570 """Locate the end of the selection nearest to the character
3571 given by index,
3572
3573 Then adjust that end of the selection to be at index
3574 (i.e including but not going beyond index). The other
3575 end of the selection is made the anchor point for future
3576 select to commands. If the selection isn't currently in
3577 the spinbox, then a new selection is created to include
3578 the characters between index and the most recent selection
3579 anchor point, inclusive. Returns an empty string.
3580 """
3581 return self.selection("adjust", index)
3582
3583 def selection_clear(self):
3584 """Clear the selection
3585
3586 If the selection isn't in this widget then the
3587 command has no effect. Returns an empty string.
3588 """
3589 return self.selection("clear")
3590
3591 def selection_element(self, element=None):
3592 """Sets or gets the currently selected element.
3593
3594 If a spinbutton element is specified, it will be
3595 displayed depressed
3596 """
3597 return self.selection("element", element)
3598
3599###########################################################################
3600
3601class LabelFrame(Widget):
3602 """labelframe widget."""
3603 def __init__(self, master=None, cnf={}, **kw):
3604 """Construct a labelframe widget with the parent MASTER.
3605
3606 STANDARD OPTIONS
3607
3608 borderwidth, cursor, font, foreground,
3609 highlightbackground, highlightcolor,
3610 highlightthickness, padx, pady, relief,
3611 takefocus, text
3612
3613 WIDGET-SPECIFIC OPTIONS
3614
3615 background, class, colormap, container,
3616 height, labelanchor, labelwidget,
3617 visual, width
3618 """
3619 Widget.__init__(self, master, 'labelframe', cnf, kw)
3620
3621########################################################################
3622
3623class PanedWindow(Widget):
3624 """panedwindow widget."""
3625 def __init__(self, master=None, cnf={}, **kw):
3626 """Construct a panedwindow widget with the parent MASTER.
3627
3628 STANDARD OPTIONS
3629
3630 background, borderwidth, cursor, height,
3631 orient, relief, width
3632
3633 WIDGET-SPECIFIC OPTIONS
3634
3635 handlepad, handlesize, opaqueresize,
3636 sashcursor, sashpad, sashrelief,
3637 sashwidth, showhandle,
3638 """
3639 Widget.__init__(self, master, 'panedwindow', cnf, kw)
3640
3641 def add(self, child, **kw):
3642 """Add a child widget to the panedwindow in a new pane.
3643
3644 The child argument is the name of the child widget
3645 followed by pairs of arguments that specify how to
Guilherme Polo1c6787f2009-05-31 21:31:21 +00003646 manage the windows. The possible options and values
3647 are the ones accepted by the paneconfigure method.
Georg Brandl33cece02008-05-20 06:58:21 +00003648 """
3649 self.tk.call((self._w, 'add', child) + self._options(kw))
3650
3651 def remove(self, child):
3652 """Remove the pane containing child from the panedwindow
3653
3654 All geometry management options for child will be forgotten.
3655 """
3656 self.tk.call(self._w, 'forget', child)
3657 forget=remove
3658
3659 def identify(self, x, y):
3660 """Identify the panedwindow component at point x, y
3661
3662 If the point is over a sash or a sash handle, the result
3663 is a two element list containing the index of the sash or
3664 handle, and a word indicating whether it is over a sash
3665 or a handle, such as {0 sash} or {2 handle}. If the point
3666 is over any other part of the panedwindow, the result is
3667 an empty list.
3668 """
3669 return self.tk.call(self._w, 'identify', x, y)
3670
3671 def proxy(self, *args):
3672 """Internal function."""
3673 return self._getints(
3674 self.tk.call((self._w, 'proxy') + args)) or ()
3675
3676 def proxy_coord(self):
3677 """Return the x and y pair of the most recent proxy location
3678 """
3679 return self.proxy("coord")
3680
3681 def proxy_forget(self):
3682 """Remove the proxy from the display.
3683 """
3684 return self.proxy("forget")
3685
3686 def proxy_place(self, x, y):
3687 """Place the proxy at the given x and y coordinates.
3688 """
3689 return self.proxy("place", x, y)
3690
3691 def sash(self, *args):
3692 """Internal function."""
3693 return self._getints(
3694 self.tk.call((self._w, 'sash') + args)) or ()
3695
3696 def sash_coord(self, index):
3697 """Return the current x and y pair for the sash given by index.
3698
3699 Index must be an integer between 0 and 1 less than the
3700 number of panes in the panedwindow. The coordinates given are
3701 those of the top left corner of the region containing the sash.
3702 pathName sash dragto index x y This command computes the
3703 difference between the given coordinates and the coordinates
3704 given to the last sash coord command for the given sash. It then
3705 moves that sash the computed difference. The return value is the
3706 empty string.
3707 """
3708 return self.sash("coord", index)
3709
3710 def sash_mark(self, index):
3711 """Records x and y for the sash given by index;
3712
3713 Used in conjunction with later dragto commands to move the sash.
3714 """
3715 return self.sash("mark", index)
3716
3717 def sash_place(self, index, x, y):
3718 """Place the sash given by index at the given coordinates
3719 """
3720 return self.sash("place", index, x, y)
3721
3722 def panecget(self, child, option):
3723 """Query a management option for window.
3724
3725 Option may be any value allowed by the paneconfigure subcommand
3726 """
3727 return self.tk.call(
3728 (self._w, 'panecget') + (child, '-'+option))
3729
3730 def paneconfigure(self, tagOrId, cnf=None, **kw):
3731 """Query or modify the management options for window.
3732
3733 If no option is specified, returns a list describing all
3734 of the available options for pathName. If option is
3735 specified with no value, then the command returns a list
3736 describing the one named option (this list will be identical
3737 to the corresponding sublist of the value returned if no
3738 option is specified). If one or more option-value pairs are
3739 specified, then the command modifies the given widget
3740 option(s) to have the given value(s); in this case the
3741 command returns an empty string. The following options
3742 are supported:
3743
3744 after window
3745 Insert the window after the window specified. window
3746 should be the name of a window already managed by pathName.
3747 before window
3748 Insert the window before the window specified. window
3749 should be the name of a window already managed by pathName.
3750 height size
3751 Specify a height for the window. The height will be the
3752 outer dimension of the window including its border, if
3753 any. If size is an empty string, or if -height is not
3754 specified, then the height requested internally by the
3755 window will be used initially; the height may later be
3756 adjusted by the movement of sashes in the panedwindow.
3757 Size may be any value accepted by Tk_GetPixels.
3758 minsize n
3759 Specifies that the size of the window cannot be made
3760 less than n. This constraint only affects the size of
3761 the widget in the paned dimension -- the x dimension
3762 for horizontal panedwindows, the y dimension for
3763 vertical panedwindows. May be any value accepted by
3764 Tk_GetPixels.
3765 padx n
3766 Specifies a non-negative value indicating how much
3767 extra space to leave on each side of the window in
3768 the X-direction. The value may have any of the forms
3769 accepted by Tk_GetPixels.
3770 pady n
3771 Specifies a non-negative value indicating how much
3772 extra space to leave on each side of the window in
3773 the Y-direction. The value may have any of the forms
3774 accepted by Tk_GetPixels.
3775 sticky style
3776 If a window's pane is larger than the requested
3777 dimensions of the window, this option may be used
3778 to position (or stretch) the window within its pane.
3779 Style is a string that contains zero or more of the
3780 characters n, s, e or w. The string can optionally
3781 contains spaces or commas, but they are ignored. Each
3782 letter refers to a side (north, south, east, or west)
3783 that the window will "stick" to. If both n and s
3784 (or e and w) are specified, the window will be
3785 stretched to fill the entire height (or width) of
3786 its cavity.
3787 width size
3788 Specify a width for the window. The width will be
3789 the outer dimension of the window including its
3790 border, if any. If size is an empty string, or
3791 if -width is not specified, then the width requested
3792 internally by the window will be used initially; the
3793 width may later be adjusted by the movement of sashes
3794 in the panedwindow. Size may be any value accepted by
3795 Tk_GetPixels.
3796
3797 """
3798 if cnf is None and not kw:
Serhiy Storchakaec773cc2013-12-25 16:35:20 +02003799 return self._getconfigure(self._w, 'paneconfigure', tagOrId)
Georg Brandl33cece02008-05-20 06:58:21 +00003800 if type(cnf) == StringType and not kw:
Serhiy Storchakaec773cc2013-12-25 16:35:20 +02003801 return self._getconfigure1(
3802 self._w, 'paneconfigure', tagOrId, '-'+cnf)
Georg Brandl33cece02008-05-20 06:58:21 +00003803 self.tk.call((self._w, 'paneconfigure', tagOrId) +
3804 self._options(cnf, kw))
3805 paneconfig = paneconfigure
3806
3807 def panes(self):
3808 """Returns an ordered list of the child panes."""
Serhiy Storchaka9be238d2014-01-07 19:32:58 +02003809 return self.tk.splitlist(self.tk.call(self._w, 'panes'))
Georg Brandl33cece02008-05-20 06:58:21 +00003810
3811######################################################################
3812# Extensions:
3813
3814class Studbutton(Button):
3815 def __init__(self, master=None, cnf={}, **kw):
3816 Widget.__init__(self, master, 'studbutton', cnf, kw)
3817 self.bind('<Any-Enter>', self.tkButtonEnter)
3818 self.bind('<Any-Leave>', self.tkButtonLeave)
3819 self.bind('<1>', self.tkButtonDown)
3820 self.bind('<ButtonRelease-1>', self.tkButtonUp)
3821
3822class Tributton(Button):
3823 def __init__(self, master=None, cnf={}, **kw):
3824 Widget.__init__(self, master, 'tributton', cnf, kw)
3825 self.bind('<Any-Enter>', self.tkButtonEnter)
3826 self.bind('<Any-Leave>', self.tkButtonLeave)
3827 self.bind('<1>', self.tkButtonDown)
3828 self.bind('<ButtonRelease-1>', self.tkButtonUp)
3829 self['fg'] = self['bg']
3830 self['activebackground'] = self['bg']
3831
3832######################################################################
3833# Test:
3834
3835def _test():
3836 root = Tk()
3837 text = "This is Tcl/Tk version %s" % TclVersion
3838 if TclVersion >= 8.1:
3839 try:
3840 text = text + unicode("\nThis should be a cedilla: \347",
3841 "iso-8859-1")
3842 except NameError:
3843 pass # no unicode support
3844 label = Label(root, text=text)
3845 label.pack()
3846 test = Button(root, text="Click me!",
3847 command=lambda root=root: root.test.configure(
3848 text="[%s]" % root.test['text']))
3849 test.pack()
3850 root.test = test
3851 quit = Button(root, text="QUIT", command=root.destroy)
3852 quit.pack()
3853 # The following three commands are needed so the window pops
3854 # up on top on Windows...
3855 root.iconify()
3856 root.update()
3857 root.deiconify()
3858 root.mainloop()
3859
3860if __name__ == '__main__':
3861 _test()