1"""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): 21import tkinter 22from tkinter.constants import * 23tk = tkinter.Tk() 24frame = tkinter.Frame(tk, relief=RIDGE, borderwidth=2) 25frame.pack(fill=BOTH,expand=1) 26label = tkinter.Label(frame, text="Hello, World") 27label.pack(fill=X, expand=1) 28button = tkinter.Button(frame,text="Exit",command=tk.destroy) 29button.pack(side=BOTTOM) 30tk.mainloop() 31""" 32 33import collections 34import enum 35import sys 36import types 37 38import _tkinter # If this fails your Python may not be configured for Tk 39TclError = _tkinter.TclError 40from tkinter.constants import * 41import re 42 43wantobjects = 1 44 45TkVersion = float(_tkinter.TK_VERSION) 46TclVersion = float(_tkinter.TCL_VERSION) 47 48READABLE = _tkinter.READABLE 49WRITABLE = _tkinter.WRITABLE 50EXCEPTION = _tkinter.EXCEPTION 51 52 53_magic_re = re.compile(r'([\\{}])') 54_space_re = re.compile(r'([\s])', re.ASCII) 55 56 57def _join(value): 58 """Internal function.""" 59 return ' '.join(map(_stringify, value)) 60 61 62def _stringify(value): 63 """Internal function.""" 64 if isinstance(value, (list, tuple)): 65 if len(value) == 1: 66 value = _stringify(value[0]) 67 if _magic_re.search(value): 68 value = '{%s}' % value 69 else: 70 value = '{%s}' % _join(value) 71 else: 72 value = str(value) 73 if not value: 74 value = '{}' 75 elif _magic_re.search(value): 76 # add '\' before special characters and spaces 77 value = _magic_re.sub(r'\\\1', value) 78 value = value.replace('\n', r'\n') 79 value = _space_re.sub(r'\\\1', value) 80 if value[0] == '"': 81 value = '\\' + value 82 elif value[0] == '"' or _space_re.search(value): 83 value = '{%s}' % value 84 return value 85 86 87def _flatten(seq): 88 """Internal function.""" 89 res = () 90 for item in seq: 91 if isinstance(item, (tuple, list)): 92 res = res + _flatten(item) 93 elif item is not None: 94 res = res + (item,) 95 return res 96 97 98try: _flatten = _tkinter._flatten 99except AttributeError: pass 100 101 102def _cnfmerge(cnfs): 103 """Internal function.""" 104 if isinstance(cnfs, dict): 105 return cnfs 106 elif isinstance(cnfs, (type(None), str)): 107 return cnfs 108 else: 109 cnf = {} 110 for c in _flatten(cnfs): 111 try: 112 cnf.update(c) 113 except (AttributeError, TypeError) as msg: 114 print("_cnfmerge: fallback due to:", msg) 115 for k, v in c.items(): 116 cnf[k] = v 117 return cnf 118 119 120try: _cnfmerge = _tkinter._cnfmerge 121except AttributeError: pass 122 123 124def _splitdict(tk, v, cut_minus=True, conv=None): 125 """Return a properly formatted dict built from Tcl list pairs. 126 127 If cut_minus is True, the supposed '-' prefix will be removed from 128 keys. If conv is specified, it is used to convert values. 129 130 Tcl list is expected to contain an even number of elements. 131 """ 132 t = tk.splitlist(v) 133 if len(t) % 2: 134 raise RuntimeError('Tcl list representing a dict is expected ' 135 'to contain an even number of elements') 136 it = iter(t) 137 dict = {} 138 for key, value in zip(it, it): 139 key = str(key) 140 if cut_minus and key[0] == '-': 141 key = key[1:] 142 if conv: 143 value = conv(value) 144 dict[key] = value 145 return dict 146 147class _VersionInfoType(collections.namedtuple('_VersionInfoType', 148 ('major', 'minor', 'micro', 'releaselevel', 'serial'))): 149 def __str__(self): 150 if self.releaselevel == 'final': 151 return f'{self.major}.{self.minor}.{self.micro}' 152 else: 153 return f'{self.major}.{self.minor}{self.releaselevel[0]}{self.serial}' 154 155def _parse_version(version): 156 import re 157 m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', version) 158 major, minor, releaselevel, serial = m.groups() 159 major, minor, serial = int(major), int(minor), int(serial) 160 if releaselevel == '.': 161 micro = serial 162 serial = 0 163 releaselevel = 'final' 164 else: 165 micro = 0 166 releaselevel = {'a': 'alpha', 'b': 'beta'}[releaselevel] 167 return _VersionInfoType(major, minor, micro, releaselevel, serial) 168 169 170@enum._simple_enum(enum.StrEnum) 171class EventType: 172 KeyPress = '2' 173 Key = KeyPress 174 KeyRelease = '3' 175 ButtonPress = '4' 176 Button = ButtonPress 177 ButtonRelease = '5' 178 Motion = '6' 179 Enter = '7' 180 Leave = '8' 181 FocusIn = '9' 182 FocusOut = '10' 183 Keymap = '11' # undocumented 184 Expose = '12' 185 GraphicsExpose = '13' # undocumented 186 NoExpose = '14' # undocumented 187 Visibility = '15' 188 Create = '16' 189 Destroy = '17' 190 Unmap = '18' 191 Map = '19' 192 MapRequest = '20' 193 Reparent = '21' 194 Configure = '22' 195 ConfigureRequest = '23' 196 Gravity = '24' 197 ResizeRequest = '25' 198 Circulate = '26' 199 CirculateRequest = '27' 200 Property = '28' 201 SelectionClear = '29' # undocumented 202 SelectionRequest = '30' # undocumented 203 Selection = '31' # undocumented 204 Colormap = '32' 205 ClientMessage = '33' # undocumented 206 Mapping = '34' # undocumented 207 VirtualEvent = '35' # undocumented 208 Activate = '36' 209 Deactivate = '37' 210 MouseWheel = '38' 211 212 213class Event: 214 """Container for the properties of an event. 215 216 Instances of this type are generated if one of the following events occurs: 217 218 KeyPress, KeyRelease - for keyboard events 219 ButtonPress, ButtonRelease, Motion, Enter, Leave, MouseWheel - for mouse events 220 Visibility, Unmap, Map, Expose, FocusIn, FocusOut, Circulate, 221 Colormap, Gravity, Reparent, Property, Destroy, Activate, 222 Deactivate - for window events. 223 224 If a callback function for one of these events is registered 225 using bind, bind_all, bind_class, or tag_bind, the callback is 226 called with an Event as first argument. It will have the 227 following attributes (in braces are the event types for which 228 the attribute is valid): 229 230 serial - serial number of event 231 num - mouse button pressed (ButtonPress, ButtonRelease) 232 focus - whether the window has the focus (Enter, Leave) 233 height - height of the exposed window (Configure, Expose) 234 width - width of the exposed window (Configure, Expose) 235 keycode - keycode of the pressed key (KeyPress, KeyRelease) 236 state - state of the event as a number (ButtonPress, ButtonRelease, 237 Enter, KeyPress, KeyRelease, 238 Leave, Motion) 239 state - state as a string (Visibility) 240 time - when the event occurred 241 x - x-position of the mouse 242 y - y-position of the mouse 243 x_root - x-position of the mouse on the screen 244 (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion) 245 y_root - y-position of the mouse on the screen 246 (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion) 247 char - pressed character (KeyPress, KeyRelease) 248 send_event - see X/Windows documentation 249 keysym - keysym of the event as a string (KeyPress, KeyRelease) 250 keysym_num - keysym of the event as a number (KeyPress, KeyRelease) 251 type - type of the event as a number 252 widget - widget in which the event occurred 253 delta - delta of wheel movement (MouseWheel) 254 """ 255 256 def __repr__(self): 257 attrs = {k: v for k, v in self.__dict__.items() if v != '??'} 258 if not self.char: 259 del attrs['char'] 260 elif self.char != '??': 261 attrs['char'] = repr(self.char) 262 if not getattr(self, 'send_event', True): 263 del attrs['send_event'] 264 if self.state == 0: 265 del attrs['state'] 266 elif isinstance(self.state, int): 267 state = self.state 268 mods = ('Shift', 'Lock', 'Control', 269 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 270 'Button1', 'Button2', 'Button3', 'Button4', 'Button5') 271 s = [] 272 for i, n in enumerate(mods): 273 if state & (1 << i): 274 s.append(n) 275 state = state & ~((1<< len(mods)) - 1) 276 if state or not s: 277 s.append(hex(state)) 278 attrs['state'] = '|'.join(s) 279 if self.delta == 0: 280 del attrs['delta'] 281 # widget usually is known 282 # serial and time are not very interesting 283 # keysym_num duplicates keysym 284 # x_root and y_root mostly duplicate x and y 285 keys = ('send_event', 286 'state', 'keysym', 'keycode', 'char', 287 'num', 'delta', 'focus', 288 'x', 'y', 'width', 'height') 289 return '<%s event%s>' % ( 290 getattr(self.type, 'name', self.type), 291 ''.join(' %s=%s' % (k, attrs[k]) for k in keys if k in attrs) 292 ) 293 294 295_support_default_root = True 296_default_root = None 297 298 299def NoDefaultRoot(): 300 """Inhibit setting of default root window. 301 302 Call this function to inhibit that the first instance of 303 Tk is used for windows without an explicit parent window. 304 """ 305 global _support_default_root, _default_root 306 _support_default_root = False 307 # Delete, so any use of _default_root will immediately raise an exception. 308 # Rebind before deletion, so repeated calls will not fail. 309 _default_root = None 310 del _default_root 311 312 313def _get_default_root(what=None): 314 if not _support_default_root: 315 raise RuntimeError("No master specified and tkinter is " 316 "configured to not support default root") 317 if _default_root is None: 318 if what: 319 raise RuntimeError(f"Too early to {what}: no default root window") 320 root = Tk() 321 assert _default_root is root 322 return _default_root 323 324 325def _get_temp_root(): 326 global _support_default_root 327 if not _support_default_root: 328 raise RuntimeError("No master specified and tkinter is " 329 "configured to not support default root") 330 root = _default_root 331 if root is None: 332 assert _support_default_root 333 _support_default_root = False 334 root = Tk() 335 _support_default_root = True 336 assert _default_root is None 337 root.withdraw() 338 root._temporary = True 339 return root 340 341 342def _destroy_temp_root(master): 343 if getattr(master, '_temporary', False): 344 try: 345 master.destroy() 346 except TclError: 347 pass 348 349 350def _tkerror(err): 351 """Internal function.""" 352 pass 353 354 355def _exit(code=0): 356 """Internal function. Calling it will raise the exception SystemExit.""" 357 try: 358 code = int(code) 359 except ValueError: 360 pass 361 raise SystemExit(code) 362 363 364_varnum = 0 365 366 367class Variable: 368 """Class to define value holders for e.g. buttons. 369 370 Subclasses StringVar, IntVar, DoubleVar, BooleanVar are specializations 371 that constrain the type of the value returned from get().""" 372 _default = "" 373 _tk = None 374 _tclCommands = None 375 376 def __init__(self, master=None, value=None, name=None): 377 """Construct a variable 378 379 MASTER can be given as master widget. 380 VALUE is an optional value (defaults to "") 381 NAME is an optional Tcl name (defaults to PY_VARnum). 382 383 If NAME matches an existing variable and VALUE is omitted 384 then the existing value is retained. 385 """ 386 # check for type of NAME parameter to override weird error message 387 # raised from Modules/_tkinter.c:SetVar like: 388 # TypeError: setvar() takes exactly 3 arguments (2 given) 389 if name is not None and not isinstance(name, str): 390 raise TypeError("name must be a string") 391 global _varnum 392 if master is None: 393 master = _get_default_root('create variable') 394 self._root = master._root() 395 self._tk = master.tk 396 if name: 397 self._name = name 398 else: 399 self._name = 'PY_VAR' + repr(_varnum) 400 _varnum += 1 401 if value is not None: 402 self.initialize(value) 403 elif not self._tk.getboolean(self._tk.call("info", "exists", self._name)): 404 self.initialize(self._default) 405 406 def __del__(self): 407 """Unset the variable in Tcl.""" 408 if self._tk is None: 409 return 410 if self._tk.getboolean(self._tk.call("info", "exists", self._name)): 411 self._tk.globalunsetvar(self._name) 412 if self._tclCommands is not None: 413 for name in self._tclCommands: 414 #print '- Tkinter: deleted command', name 415 self._tk.deletecommand(name) 416 self._tclCommands = None 417 418 def __str__(self): 419 """Return the name of the variable in Tcl.""" 420 return self._name 421 422 def set(self, value): 423 """Set the variable to VALUE.""" 424 return self._tk.globalsetvar(self._name, value) 425 426 initialize = set 427 428 def get(self): 429 """Return value of variable.""" 430 return self._tk.globalgetvar(self._name) 431 432 def _register(self, callback): 433 f = CallWrapper(callback, None, self._root).__call__ 434 cbname = repr(id(f)) 435 try: 436 callback = callback.__func__ 437 except AttributeError: 438 pass 439 try: 440 cbname = cbname + callback.__name__ 441 except AttributeError: 442 pass 443 self._tk.createcommand(cbname, f) 444 if self._tclCommands is None: 445 self._tclCommands = [] 446 self._tclCommands.append(cbname) 447 return cbname 448 449 def trace_add(self, mode, callback): 450 """Define a trace callback for the variable. 451 452 Mode is one of "read", "write", "unset", or a list or tuple of 453 such strings. 454 Callback must be a function which is called when the variable is 455 read, written or unset. 456 457 Return the name of the callback. 458 """ 459 cbname = self._register(callback) 460 self._tk.call('trace', 'add', 'variable', 461 self._name, mode, (cbname,)) 462 return cbname 463 464 def trace_remove(self, mode, cbname): 465 """Delete the trace callback for a variable. 466 467 Mode is one of "read", "write", "unset" or a list or tuple of 468 such strings. Must be same as were specified in trace_add(). 469 cbname is the name of the callback returned from trace_add(). 470 """ 471 self._tk.call('trace', 'remove', 'variable', 472 self._name, mode, cbname) 473 for m, ca in self.trace_info(): 474 if self._tk.splitlist(ca)[0] == cbname: 475 break 476 else: 477 self._tk.deletecommand(cbname) 478 try: 479 self._tclCommands.remove(cbname) 480 except ValueError: 481 pass 482 483 def trace_info(self): 484 """Return all trace callback information.""" 485 splitlist = self._tk.splitlist 486 return [(splitlist(k), v) for k, v in map(splitlist, 487 splitlist(self._tk.call('trace', 'info', 'variable', self._name)))] 488 489 def trace_variable(self, mode, callback): 490 """Define a trace callback for the variable. 491 492 MODE is one of "r", "w", "u" for read, write, undefine. 493 CALLBACK must be a function which is called when 494 the variable is read, written or undefined. 495 496 Return the name of the callback. 497 498 This deprecated method wraps a deprecated Tcl method that will 499 likely be removed in the future. Use trace_add() instead. 500 """ 501 # TODO: Add deprecation warning 502 cbname = self._register(callback) 503 self._tk.call("trace", "variable", self._name, mode, cbname) 504 return cbname 505 506 trace = trace_variable 507 508 def trace_vdelete(self, mode, cbname): 509 """Delete the trace callback for a variable. 510 511 MODE is one of "r", "w", "u" for read, write, undefine. 512 CBNAME is the name of the callback returned from trace_variable or trace. 513 514 This deprecated method wraps a deprecated Tcl method that will 515 likely be removed in the future. Use trace_remove() instead. 516 """ 517 # TODO: Add deprecation warning 518 self._tk.call("trace", "vdelete", self._name, mode, cbname) 519 cbname = self._tk.splitlist(cbname)[0] 520 for m, ca in self.trace_info(): 521 if self._tk.splitlist(ca)[0] == cbname: 522 break 523 else: 524 self._tk.deletecommand(cbname) 525 try: 526 self._tclCommands.remove(cbname) 527 except ValueError: 528 pass 529 530 def trace_vinfo(self): 531 """Return all trace callback information. 532 533 This deprecated method wraps a deprecated Tcl method that will 534 likely be removed in the future. Use trace_info() instead. 535 """ 536 # TODO: Add deprecation warning 537 return [self._tk.splitlist(x) for x in self._tk.splitlist( 538 self._tk.call("trace", "vinfo", self._name))] 539 540 def __eq__(self, other): 541 if not isinstance(other, Variable): 542 return NotImplemented 543 return (self._name == other._name 544 and self.__class__.__name__ == other.__class__.__name__ 545 and self._tk == other._tk) 546 547 548class StringVar(Variable): 549 """Value holder for strings variables.""" 550 _default = "" 551 552 def __init__(self, master=None, value=None, name=None): 553 """Construct a string variable. 554 555 MASTER can be given as master widget. 556 VALUE is an optional value (defaults to "") 557 NAME is an optional Tcl name (defaults to PY_VARnum). 558 559 If NAME matches an existing variable and VALUE is omitted 560 then the existing value is retained. 561 """ 562 Variable.__init__(self, master, value, name) 563 564 def get(self): 565 """Return value of variable as string.""" 566 value = self._tk.globalgetvar(self._name) 567 if isinstance(value, str): 568 return value 569 return str(value) 570 571 572class IntVar(Variable): 573 """Value holder for integer variables.""" 574 _default = 0 575 576 def __init__(self, master=None, value=None, name=None): 577 """Construct an integer variable. 578 579 MASTER can be given as master widget. 580 VALUE is an optional value (defaults to 0) 581 NAME is an optional Tcl name (defaults to PY_VARnum). 582 583 If NAME matches an existing variable and VALUE is omitted 584 then the existing value is retained. 585 """ 586 Variable.__init__(self, master, value, name) 587 588 def get(self): 589 """Return the value of the variable as an integer.""" 590 value = self._tk.globalgetvar(self._name) 591 try: 592 return self._tk.getint(value) 593 except (TypeError, TclError): 594 return int(self._tk.getdouble(value)) 595 596 597class DoubleVar(Variable): 598 """Value holder for float variables.""" 599 _default = 0.0 600 601 def __init__(self, master=None, value=None, name=None): 602 """Construct a float variable. 603 604 MASTER can be given as master widget. 605 VALUE is an optional value (defaults to 0.0) 606 NAME is an optional Tcl name (defaults to PY_VARnum). 607 608 If NAME matches an existing variable and VALUE is omitted 609 then the existing value is retained. 610 """ 611 Variable.__init__(self, master, value, name) 612 613 def get(self): 614 """Return the value of the variable as a float.""" 615 return self._tk.getdouble(self._tk.globalgetvar(self._name)) 616 617 618class BooleanVar(Variable): 619 """Value holder for boolean variables.""" 620 _default = False 621 622 def __init__(self, master=None, value=None, name=None): 623 """Construct a boolean variable. 624 625 MASTER can be given as master widget. 626 VALUE is an optional value (defaults to False) 627 NAME is an optional Tcl name (defaults to PY_VARnum). 628 629 If NAME matches an existing variable and VALUE is omitted 630 then the existing value is retained. 631 """ 632 Variable.__init__(self, master, value, name) 633 634 def set(self, value): 635 """Set the variable to VALUE.""" 636 return self._tk.globalsetvar(self._name, self._tk.getboolean(value)) 637 638 initialize = set 639 640 def get(self): 641 """Return the value of the variable as a bool.""" 642 try: 643 return self._tk.getboolean(self._tk.globalgetvar(self._name)) 644 except TclError: 645 raise ValueError("invalid literal for getboolean()") 646 647 648def mainloop(n=0): 649 """Run the main loop of Tcl.""" 650 _get_default_root('run the main loop').tk.mainloop(n) 651 652 653getint = int 654 655getdouble = float 656 657 658def getboolean(s): 659 """Convert Tcl object to True or False.""" 660 try: 661 return _get_default_root('use getboolean()').tk.getboolean(s) 662 except TclError: 663 raise ValueError("invalid literal for getboolean()") 664 665 666# Methods defined on both toplevel and interior widgets 667 668class Misc: 669 """Internal class. 670 671 Base class which defines methods common for interior widgets.""" 672 673 # used for generating child widget names 674 _last_child_ids = None 675 676 # XXX font command? 677 _tclCommands = None 678 679 def destroy(self): 680 """Internal function. 681 682 Delete all Tcl commands created for 683 this widget in the Tcl interpreter.""" 684 if self._tclCommands is not None: 685 for name in self._tclCommands: 686 #print '- Tkinter: deleted command', name 687 self.tk.deletecommand(name) 688 self._tclCommands = None 689 690 def deletecommand(self, name): 691 """Internal function. 692 693 Delete the Tcl command provided in NAME.""" 694 #print '- Tkinter: deleted command', name 695 self.tk.deletecommand(name) 696 try: 697 self._tclCommands.remove(name) 698 except ValueError: 699 pass 700 701 def tk_strictMotif(self, boolean=None): 702 """Set Tcl internal variable, whether the look and feel 703 should adhere to Motif. 704 705 A parameter of 1 means adhere to Motif (e.g. no color 706 change if mouse passes over slider). 707 Returns the set value.""" 708 return self.tk.getboolean(self.tk.call( 709 'set', 'tk_strictMotif', boolean)) 710 711 def tk_bisque(self): 712 """Change the color scheme to light brown as used in Tk 3.6 and before.""" 713 self.tk.call('tk_bisque') 714 715 def tk_setPalette(self, *args, **kw): 716 """Set a new color scheme for all widget elements. 717 718 A single color as argument will cause that all colors of Tk 719 widget elements are derived from this. 720 Alternatively several keyword parameters and its associated 721 colors can be given. The following keywords are valid: 722 activeBackground, foreground, selectColor, 723 activeForeground, highlightBackground, selectBackground, 724 background, highlightColor, selectForeground, 725 disabledForeground, insertBackground, troughColor.""" 726 self.tk.call(('tk_setPalette',) 727 + _flatten(args) + _flatten(list(kw.items()))) 728 729 def wait_variable(self, name='PY_VAR'): 730 """Wait until the variable is modified. 731 732 A parameter of type IntVar, StringVar, DoubleVar or 733 BooleanVar must be given.""" 734 self.tk.call('tkwait', 'variable', name) 735 waitvar = wait_variable # XXX b/w compat 736 737 def wait_window(self, window=None): 738 """Wait until a WIDGET is destroyed. 739 740 If no parameter is given self is used.""" 741 if window is None: 742 window = self 743 self.tk.call('tkwait', 'window', window._w) 744 745 def wait_visibility(self, window=None): 746 """Wait until the visibility of a WIDGET changes 747 (e.g. it appears). 748 749 If no parameter is given self is used.""" 750 if window is None: 751 window = self 752 self.tk.call('tkwait', 'visibility', window._w) 753 754 def setvar(self, name='PY_VAR', value='1'): 755 """Set Tcl variable NAME to VALUE.""" 756 self.tk.setvar(name, value) 757 758 def getvar(self, name='PY_VAR'): 759 """Return value of Tcl variable NAME.""" 760 return self.tk.getvar(name) 761 762 def getint(self, s): 763 try: 764 return self.tk.getint(s) 765 except TclError as exc: 766 raise ValueError(str(exc)) 767 768 def getdouble(self, s): 769 try: 770 return self.tk.getdouble(s) 771 except TclError as exc: 772 raise ValueError(str(exc)) 773 774 def getboolean(self, s): 775 """Return a boolean value for Tcl boolean values true and false given as parameter.""" 776 try: 777 return self.tk.getboolean(s) 778 except TclError: 779 raise ValueError("invalid literal for getboolean()") 780 781 def focus_set(self): 782 """Direct input focus to this widget. 783 784 If the application currently does not have the focus 785 this widget will get the focus if the application gets 786 the focus through the window manager.""" 787 self.tk.call('focus', self._w) 788 focus = focus_set # XXX b/w compat? 789 790 def focus_force(self): 791 """Direct input focus to this widget even if the 792 application does not have the focus. Use with 793 caution!""" 794 self.tk.call('focus', '-force', self._w) 795 796 def focus_get(self): 797 """Return the widget which has currently the focus in the 798 application. 799 800 Use focus_displayof to allow working with several 801 displays. Return None if application does not have 802 the focus.""" 803 name = self.tk.call('focus') 804 if name == 'none' or not name: return None 805 return self._nametowidget(name) 806 807 def focus_displayof(self): 808 """Return the widget which has currently the focus on the 809 display where this widget is located. 810 811 Return None if the application does not have the focus.""" 812 name = self.tk.call('focus', '-displayof', self._w) 813 if name == 'none' or not name: return None 814 return self._nametowidget(name) 815 816 def focus_lastfor(self): 817 """Return the widget which would have the focus if top level 818 for this widget gets the focus from the window manager.""" 819 name = self.tk.call('focus', '-lastfor', self._w) 820 if name == 'none' or not name: return None 821 return self._nametowidget(name) 822 823 def tk_focusFollowsMouse(self): 824 """The widget under mouse will get automatically focus. Can not 825 be disabled easily.""" 826 self.tk.call('tk_focusFollowsMouse') 827 828 def tk_focusNext(self): 829 """Return the next widget in the focus order which follows 830 widget which has currently the focus. 831 832 The focus order first goes to the next child, then to 833 the children of the child recursively and then to the 834 next sibling which is higher in the stacking order. A 835 widget is omitted if it has the takefocus resource set 836 to 0.""" 837 name = self.tk.call('tk_focusNext', self._w) 838 if not name: return None 839 return self._nametowidget(name) 840 841 def tk_focusPrev(self): 842 """Return previous widget in the focus order. See tk_focusNext for details.""" 843 name = self.tk.call('tk_focusPrev', self._w) 844 if not name: return None 845 return self._nametowidget(name) 846 847 def after(self, ms, func=None, *args): 848 """Call function once after given time. 849 850 MS specifies the time in milliseconds. FUNC gives the 851 function which shall be called. Additional parameters 852 are given as parameters to the function call. Return 853 identifier to cancel scheduling with after_cancel.""" 854 if func is None: 855 # I'd rather use time.sleep(ms*0.001) 856 self.tk.call('after', ms) 857 return None 858 else: 859 def callit(): 860 try: 861 func(*args) 862 finally: 863 try: 864 self.deletecommand(name) 865 except TclError: 866 pass 867 try: 868 callit.__name__ = func.__name__ 869 except AttributeError: 870 # Required for callable classes (bpo-44404) 871 callit.__name__ = type(func).__name__ 872 name = self._register(callit) 873 return self.tk.call('after', ms, name) 874 875 def after_idle(self, func, *args): 876 """Call FUNC once if the Tcl main loop has no event to 877 process. 878 879 Return an identifier to cancel the scheduling with 880 after_cancel.""" 881 return self.after('idle', func, *args) 882 883 def after_cancel(self, id): 884 """Cancel scheduling of function identified with ID. 885 886 Identifier returned by after or after_idle must be 887 given as first parameter. 888 """ 889 if not id: 890 raise ValueError('id must be a valid identifier returned from ' 891 'after or after_idle') 892 try: 893 data = self.tk.call('after', 'info', id) 894 script = self.tk.splitlist(data)[0] 895 self.deletecommand(script) 896 except TclError: 897 pass 898 self.tk.call('after', 'cancel', id) 899 900 def bell(self, displayof=0): 901 """Ring a display's bell.""" 902 self.tk.call(('bell',) + self._displayof(displayof)) 903 904 # Clipboard handling: 905 def clipboard_get(self, **kw): 906 """Retrieve data from the clipboard on window's display. 907 908 The window keyword defaults to the root window of the Tkinter 909 application. 910 911 The type keyword specifies the form in which the data is 912 to be returned and should be an atom name such as STRING 913 or FILE_NAME. Type defaults to STRING, except on X11, where the default 914 is to try UTF8_STRING and fall back to STRING. 915 916 This command is equivalent to: 917 918 selection_get(CLIPBOARD) 919 """ 920 if 'type' not in kw and self._windowingsystem == 'x11': 921 try: 922 kw['type'] = 'UTF8_STRING' 923 return self.tk.call(('clipboard', 'get') + self._options(kw)) 924 except TclError: 925 del kw['type'] 926 return self.tk.call(('clipboard', 'get') + self._options(kw)) 927 928 def clipboard_clear(self, **kw): 929 """Clear the data in the Tk clipboard. 930 931 A widget specified for the optional displayof keyword 932 argument specifies the target display.""" 933 if 'displayof' not in kw: kw['displayof'] = self._w 934 self.tk.call(('clipboard', 'clear') + self._options(kw)) 935 936 def clipboard_append(self, string, **kw): 937 """Append STRING to the Tk clipboard. 938 939 A widget specified at the optional displayof keyword 940 argument specifies the target display. The clipboard 941 can be retrieved with selection_get.""" 942 if 'displayof' not in kw: kw['displayof'] = self._w 943 self.tk.call(('clipboard', 'append') + self._options(kw) 944 + ('--', string)) 945 # XXX grab current w/o window argument 946 947 def grab_current(self): 948 """Return widget which has currently the grab in this application 949 or None.""" 950 name = self.tk.call('grab', 'current', self._w) 951 if not name: return None 952 return self._nametowidget(name) 953 954 def grab_release(self): 955 """Release grab for this widget if currently set.""" 956 self.tk.call('grab', 'release', self._w) 957 958 def grab_set(self): 959 """Set grab for this widget. 960 961 A grab directs all events to this and descendant 962 widgets in the application.""" 963 self.tk.call('grab', 'set', self._w) 964 965 def grab_set_global(self): 966 """Set global grab for this widget. 967 968 A global grab directs all events to this and 969 descendant widgets on the display. Use with caution - 970 other applications do not get events anymore.""" 971 self.tk.call('grab', 'set', '-global', self._w) 972 973 def grab_status(self): 974 """Return None, "local" or "global" if this widget has 975 no, a local or a global grab.""" 976 status = self.tk.call('grab', 'status', self._w) 977 if status == 'none': status = None 978 return status 979 980 def option_add(self, pattern, value, priority = None): 981 """Set a VALUE (second parameter) for an option 982 PATTERN (first parameter). 983 984 An optional third parameter gives the numeric priority 985 (defaults to 80).""" 986 self.tk.call('option', 'add', pattern, value, priority) 987 988 def option_clear(self): 989 """Clear the option database. 990 991 It will be reloaded if option_add is called.""" 992 self.tk.call('option', 'clear') 993 994 def option_get(self, name, className): 995 """Return the value for an option NAME for this widget 996 with CLASSNAME. 997 998 Values with higher priority override lower values.""" 999 return self.tk.call('option', 'get', self._w, name, className) 1000 1001 def option_readfile(self, fileName, priority = None): 1002 """Read file FILENAME into the option database. 1003 1004 An optional second parameter gives the numeric 1005 priority.""" 1006 self.tk.call('option', 'readfile', fileName, priority) 1007 1008 def selection_clear(self, **kw): 1009 """Clear the current X selection.""" 1010 if 'displayof' not in kw: kw['displayof'] = self._w 1011 self.tk.call(('selection', 'clear') + self._options(kw)) 1012 1013 def selection_get(self, **kw): 1014 """Return the contents of the current X selection. 1015 1016 A keyword parameter selection specifies the name of 1017 the selection and defaults to PRIMARY. A keyword 1018 parameter displayof specifies a widget on the display 1019 to use. A keyword parameter type specifies the form of data to be 1020 fetched, defaulting to STRING except on X11, where UTF8_STRING is tried 1021 before STRING.""" 1022 if 'displayof' not in kw: kw['displayof'] = self._w 1023 if 'type' not in kw and self._windowingsystem == 'x11': 1024 try: 1025 kw['type'] = 'UTF8_STRING' 1026 return self.tk.call(('selection', 'get') + self._options(kw)) 1027 except TclError: 1028 del kw['type'] 1029 return self.tk.call(('selection', 'get') + self._options(kw)) 1030 1031 def selection_handle(self, command, **kw): 1032 """Specify a function COMMAND to call if the X 1033 selection owned by this widget is queried by another 1034 application. 1035 1036 This function must return the contents of the 1037 selection. The function will be called with the 1038 arguments OFFSET and LENGTH which allows the chunking 1039 of very long selections. The following keyword 1040 parameters can be provided: 1041 selection - name of the selection (default PRIMARY), 1042 type - type of the selection (e.g. STRING, FILE_NAME).""" 1043 name = self._register(command) 1044 self.tk.call(('selection', 'handle') + self._options(kw) 1045 + (self._w, name)) 1046 1047 def selection_own(self, **kw): 1048 """Become owner of X selection. 1049 1050 A keyword parameter selection specifies the name of 1051 the selection (default PRIMARY).""" 1052 self.tk.call(('selection', 'own') + 1053 self._options(kw) + (self._w,)) 1054 1055 def selection_own_get(self, **kw): 1056 """Return owner of X selection. 1057 1058 The following keyword parameter can 1059 be provided: 1060 selection - name of the selection (default PRIMARY), 1061 type - type of the selection (e.g. STRING, FILE_NAME).""" 1062 if 'displayof' not in kw: kw['displayof'] = self._w 1063 name = self.tk.call(('selection', 'own') + self._options(kw)) 1064 if not name: return None 1065 return self._nametowidget(name) 1066 1067 def send(self, interp, cmd, *args): 1068 """Send Tcl command CMD to different interpreter INTERP to be executed.""" 1069 return self.tk.call(('send', interp, cmd) + args) 1070 1071 def lower(self, belowThis=None): 1072 """Lower this widget in the stacking order.""" 1073 self.tk.call('lower', self._w, belowThis) 1074 1075 def tkraise(self, aboveThis=None): 1076 """Raise this widget in the stacking order.""" 1077 self.tk.call('raise', self._w, aboveThis) 1078 1079 lift = tkraise 1080 1081 def info_patchlevel(self): 1082 """Returns the exact version of the Tcl library.""" 1083 patchlevel = self.tk.call('info', 'patchlevel') 1084 return _parse_version(patchlevel) 1085 1086 def winfo_atom(self, name, displayof=0): 1087 """Return integer which represents atom NAME.""" 1088 args = ('winfo', 'atom') + self._displayof(displayof) + (name,) 1089 return self.tk.getint(self.tk.call(args)) 1090 1091 def winfo_atomname(self, id, displayof=0): 1092 """Return name of atom with identifier ID.""" 1093 args = ('winfo', 'atomname') \ 1094 + self._displayof(displayof) + (id,) 1095 return self.tk.call(args) 1096 1097 def winfo_cells(self): 1098 """Return number of cells in the colormap for this widget.""" 1099 return self.tk.getint( 1100 self.tk.call('winfo', 'cells', self._w)) 1101 1102 def winfo_children(self): 1103 """Return a list of all widgets which are children of this widget.""" 1104 result = [] 1105 for child in self.tk.splitlist( 1106 self.tk.call('winfo', 'children', self._w)): 1107 try: 1108 # Tcl sometimes returns extra windows, e.g. for 1109 # menus; those need to be skipped 1110 result.append(self._nametowidget(child)) 1111 except KeyError: 1112 pass 1113 return result 1114 1115 def winfo_class(self): 1116 """Return window class name of this widget.""" 1117 return self.tk.call('winfo', 'class', self._w) 1118 1119 def winfo_colormapfull(self): 1120 """Return True if at the last color request the colormap was full.""" 1121 return self.tk.getboolean( 1122 self.tk.call('winfo', 'colormapfull', self._w)) 1123 1124 def winfo_containing(self, rootX, rootY, displayof=0): 1125 """Return the widget which is at the root coordinates ROOTX, ROOTY.""" 1126 args = ('winfo', 'containing') \ 1127 + self._displayof(displayof) + (rootX, rootY) 1128 name = self.tk.call(args) 1129 if not name: return None 1130 return self._nametowidget(name) 1131 1132 def winfo_depth(self): 1133 """Return the number of bits per pixel.""" 1134 return self.tk.getint(self.tk.call('winfo', 'depth', self._w)) 1135 1136 def winfo_exists(self): 1137 """Return true if this widget exists.""" 1138 return self.tk.getint( 1139 self.tk.call('winfo', 'exists', self._w)) 1140 1141 def winfo_fpixels(self, number): 1142 """Return the number of pixels for the given distance NUMBER 1143 (e.g. "3c") as float.""" 1144 return self.tk.getdouble(self.tk.call( 1145 'winfo', 'fpixels', self._w, number)) 1146 1147 def winfo_geometry(self): 1148 """Return geometry string for this widget in the form "widthxheight+X+Y".""" 1149 return self.tk.call('winfo', 'geometry', self._w) 1150 1151 def winfo_height(self): 1152 """Return height of this widget.""" 1153 return self.tk.getint( 1154 self.tk.call('winfo', 'height', self._w)) 1155 1156 def winfo_id(self): 1157 """Return identifier ID for this widget.""" 1158 return int(self.tk.call('winfo', 'id', self._w), 0) 1159 1160 def winfo_interps(self, displayof=0): 1161 """Return the name of all Tcl interpreters for this display.""" 1162 args = ('winfo', 'interps') + self._displayof(displayof) 1163 return self.tk.splitlist(self.tk.call(args)) 1164 1165 def winfo_ismapped(self): 1166 """Return true if this widget is mapped.""" 1167 return self.tk.getint( 1168 self.tk.call('winfo', 'ismapped', self._w)) 1169 1170 def winfo_manager(self): 1171 """Return the window manager name for this widget.""" 1172 return self.tk.call('winfo', 'manager', self._w) 1173 1174 def winfo_name(self): 1175 """Return the name of this widget.""" 1176 return self.tk.call('winfo', 'name', self._w) 1177 1178 def winfo_parent(self): 1179 """Return the name of the parent of this widget.""" 1180 return self.tk.call('winfo', 'parent', self._w) 1181 1182 def winfo_pathname(self, id, displayof=0): 1183 """Return the pathname of the widget given by ID.""" 1184 args = ('winfo', 'pathname') \ 1185 + self._displayof(displayof) + (id,) 1186 return self.tk.call(args) 1187 1188 def winfo_pixels(self, number): 1189 """Rounded integer value of winfo_fpixels.""" 1190 return self.tk.getint( 1191 self.tk.call('winfo', 'pixels', self._w, number)) 1192 1193 def winfo_pointerx(self): 1194 """Return the x coordinate of the pointer on the root window.""" 1195 return self.tk.getint( 1196 self.tk.call('winfo', 'pointerx', self._w)) 1197 1198 def winfo_pointerxy(self): 1199 """Return a tuple of x and y coordinates of the pointer on the root window.""" 1200 return self._getints( 1201 self.tk.call('winfo', 'pointerxy', self._w)) 1202 1203 def winfo_pointery(self): 1204 """Return the y coordinate of the pointer on the root window.""" 1205 return self.tk.getint( 1206 self.tk.call('winfo', 'pointery', self._w)) 1207 1208 def winfo_reqheight(self): 1209 """Return requested height of this widget.""" 1210 return self.tk.getint( 1211 self.tk.call('winfo', 'reqheight', self._w)) 1212 1213 def winfo_reqwidth(self): 1214 """Return requested width of this widget.""" 1215 return self.tk.getint( 1216 self.tk.call('winfo', 'reqwidth', self._w)) 1217 1218 def winfo_rgb(self, color): 1219 """Return a tuple of integer RGB values in range(65536) for color in this widget.""" 1220 return self._getints( 1221 self.tk.call('winfo', 'rgb', self._w, color)) 1222 1223 def winfo_rootx(self): 1224 """Return x coordinate of upper left corner of this widget on the 1225 root window.""" 1226 return self.tk.getint( 1227 self.tk.call('winfo', 'rootx', self._w)) 1228 1229 def winfo_rooty(self): 1230 """Return y coordinate of upper left corner of this widget on the 1231 root window.""" 1232 return self.tk.getint( 1233 self.tk.call('winfo', 'rooty', self._w)) 1234 1235 def winfo_screen(self): 1236 """Return the screen name of this widget.""" 1237 return self.tk.call('winfo', 'screen', self._w) 1238 1239 def winfo_screencells(self): 1240 """Return the number of the cells in the colormap of the screen 1241 of this widget.""" 1242 return self.tk.getint( 1243 self.tk.call('winfo', 'screencells', self._w)) 1244 1245 def winfo_screendepth(self): 1246 """Return the number of bits per pixel of the root window of the 1247 screen of this widget.""" 1248 return self.tk.getint( 1249 self.tk.call('winfo', 'screendepth', self._w)) 1250 1251 def winfo_screenheight(self): 1252 """Return the number of pixels of the height of the screen of this widget 1253 in pixel.""" 1254 return self.tk.getint( 1255 self.tk.call('winfo', 'screenheight', self._w)) 1256 1257 def winfo_screenmmheight(self): 1258 """Return the number of pixels of the height of the screen of 1259 this widget in mm.""" 1260 return self.tk.getint( 1261 self.tk.call('winfo', 'screenmmheight', self._w)) 1262 1263 def winfo_screenmmwidth(self): 1264 """Return the number of pixels of the width of the screen of 1265 this widget in mm.""" 1266 return self.tk.getint( 1267 self.tk.call('winfo', 'screenmmwidth', self._w)) 1268 1269 def winfo_screenvisual(self): 1270 """Return one of the strings directcolor, grayscale, pseudocolor, 1271 staticcolor, staticgray, or truecolor for the default 1272 colormodel of this screen.""" 1273 return self.tk.call('winfo', 'screenvisual', self._w) 1274 1275 def winfo_screenwidth(self): 1276 """Return the number of pixels of the width of the screen of 1277 this widget in pixel.""" 1278 return self.tk.getint( 1279 self.tk.call('winfo', 'screenwidth', self._w)) 1280 1281 def winfo_server(self): 1282 """Return information of the X-Server of the screen of this widget in 1283 the form "XmajorRminor vendor vendorVersion".""" 1284 return self.tk.call('winfo', 'server', self._w) 1285 1286 def winfo_toplevel(self): 1287 """Return the toplevel widget of this widget.""" 1288 return self._nametowidget(self.tk.call( 1289 'winfo', 'toplevel', self._w)) 1290 1291 def winfo_viewable(self): 1292 """Return true if the widget and all its higher ancestors are mapped.""" 1293 return self.tk.getint( 1294 self.tk.call('winfo', 'viewable', self._w)) 1295 1296 def winfo_visual(self): 1297 """Return one of the strings directcolor, grayscale, pseudocolor, 1298 staticcolor, staticgray, or truecolor for the 1299 colormodel of this widget.""" 1300 return self.tk.call('winfo', 'visual', self._w) 1301 1302 def winfo_visualid(self): 1303 """Return the X identifier for the visual for this widget.""" 1304 return self.tk.call('winfo', 'visualid', self._w) 1305 1306 def winfo_visualsavailable(self, includeids=False): 1307 """Return a list of all visuals available for the screen 1308 of this widget. 1309 1310 Each item in the list consists of a visual name (see winfo_visual), a 1311 depth and if includeids is true is given also the X identifier.""" 1312 data = self.tk.call('winfo', 'visualsavailable', self._w, 1313 'includeids' if includeids else None) 1314 data = [self.tk.splitlist(x) for x in self.tk.splitlist(data)] 1315 return [self.__winfo_parseitem(x) for x in data] 1316 1317 def __winfo_parseitem(self, t): 1318 """Internal function.""" 1319 return t[:1] + tuple(map(self.__winfo_getint, t[1:])) 1320 1321 def __winfo_getint(self, x): 1322 """Internal function.""" 1323 return int(x, 0) 1324 1325 def winfo_vrootheight(self): 1326 """Return the height of the virtual root window associated with this 1327 widget in pixels. If there is no virtual root window return the 1328 height of the screen.""" 1329 return self.tk.getint( 1330 self.tk.call('winfo', 'vrootheight', self._w)) 1331 1332 def winfo_vrootwidth(self): 1333 """Return the width of the virtual root window associated with this 1334 widget in pixel. If there is no virtual root window return the 1335 width of the screen.""" 1336 return self.tk.getint( 1337 self.tk.call('winfo', 'vrootwidth', self._w)) 1338 1339 def winfo_vrootx(self): 1340 """Return the x offset of the virtual root relative to the root 1341 window of the screen of this widget.""" 1342 return self.tk.getint( 1343 self.tk.call('winfo', 'vrootx', self._w)) 1344 1345 def winfo_vrooty(self): 1346 """Return the y offset of the virtual root relative to the root 1347 window of the screen of this widget.""" 1348 return self.tk.getint( 1349 self.tk.call('winfo', 'vrooty', self._w)) 1350 1351 def winfo_width(self): 1352 """Return the width of this widget.""" 1353 return self.tk.getint( 1354 self.tk.call('winfo', 'width', self._w)) 1355 1356 def winfo_x(self): 1357 """Return the x coordinate of the upper left corner of this widget 1358 in the parent.""" 1359 return self.tk.getint( 1360 self.tk.call('winfo', 'x', self._w)) 1361 1362 def winfo_y(self): 1363 """Return the y coordinate of the upper left corner of this widget 1364 in the parent.""" 1365 return self.tk.getint( 1366 self.tk.call('winfo', 'y', self._w)) 1367 1368 def update(self): 1369 """Enter event loop until all pending events have been processed by Tcl.""" 1370 self.tk.call('update') 1371 1372 def update_idletasks(self): 1373 """Enter event loop until all idle callbacks have been called. This 1374 will update the display of windows but not process events caused by 1375 the user.""" 1376 self.tk.call('update', 'idletasks') 1377 1378 def bindtags(self, tagList=None): 1379 """Set or get the list of bindtags for this widget. 1380 1381 With no argument return the list of all bindtags associated with 1382 this widget. With a list of strings as argument the bindtags are 1383 set to this list. The bindtags determine in which order events are 1384 processed (see bind).""" 1385 if tagList is None: 1386 return self.tk.splitlist( 1387 self.tk.call('bindtags', self._w)) 1388 else: 1389 self.tk.call('bindtags', self._w, tagList) 1390 1391 def _bind(self, what, sequence, func, add, needcleanup=1): 1392 """Internal function.""" 1393 if isinstance(func, str): 1394 self.tk.call(what + (sequence, func)) 1395 elif func: 1396 funcid = self._register(func, self._substitute, 1397 needcleanup) 1398 cmd = ('%sif {"[%s %s]" == "break"} break\n' 1399 % 1400 (add and '+' or '', 1401 funcid, self._subst_format_str)) 1402 self.tk.call(what + (sequence, cmd)) 1403 return funcid 1404 elif sequence: 1405 return self.tk.call(what + (sequence,)) 1406 else: 1407 return self.tk.splitlist(self.tk.call(what)) 1408 1409 def bind(self, sequence=None, func=None, add=None): 1410 """Bind to this widget at event SEQUENCE a call to function FUNC. 1411 1412 SEQUENCE is a string of concatenated event 1413 patterns. An event pattern is of the form 1414 <MODIFIER-MODIFIER-TYPE-DETAIL> where MODIFIER is one 1415 of Control, Mod2, M2, Shift, Mod3, M3, Lock, Mod4, M4, 1416 Button1, B1, Mod5, M5 Button2, B2, Meta, M, Button3, 1417 B3, Alt, Button4, B4, Double, Button5, B5 Triple, 1418 Mod1, M1. TYPE is one of Activate, Enter, Map, 1419 ButtonPress, Button, Expose, Motion, ButtonRelease 1420 FocusIn, MouseWheel, Circulate, FocusOut, Property, 1421 Colormap, Gravity Reparent, Configure, KeyPress, Key, 1422 Unmap, Deactivate, KeyRelease Visibility, Destroy, 1423 Leave and DETAIL is the button number for ButtonPress, 1424 ButtonRelease and DETAIL is the Keysym for KeyPress and 1425 KeyRelease. Examples are 1426 <Control-Button-1> for pressing Control and mouse button 1 or 1427 <Alt-A> for pressing A and the Alt key (KeyPress can be omitted). 1428 An event pattern can also be a virtual event of the form 1429 <<AString>> where AString can be arbitrary. This 1430 event can be generated by event_generate. 1431 If events are concatenated they must appear shortly 1432 after each other. 1433 1434 FUNC will be called if the event sequence occurs with an 1435 instance of Event as argument. If the return value of FUNC is 1436 "break" no further bound function is invoked. 1437 1438 An additional boolean parameter ADD specifies whether FUNC will 1439 be called additionally to the other bound function or whether 1440 it will replace the previous function. 1441 1442 Bind will return an identifier to allow deletion of the bound function with 1443 unbind without memory leak. 1444 1445 If FUNC or SEQUENCE is omitted the bound function or list 1446 of bound events are returned.""" 1447 1448 return self._bind(('bind', self._w), sequence, func, add) 1449 1450 def unbind(self, sequence, funcid=None): 1451 """Unbind for this widget for event SEQUENCE the 1452 function identified with FUNCID.""" 1453 self.tk.call('bind', self._w, sequence, '') 1454 if funcid: 1455 self.deletecommand(funcid) 1456 1457 def bind_all(self, sequence=None, func=None, add=None): 1458 """Bind to all widgets at an event SEQUENCE a call to function FUNC. 1459 An additional boolean parameter ADD specifies whether FUNC will 1460 be called additionally to the other bound function or whether 1461 it will replace the previous function. See bind for the return value.""" 1462 return self._bind(('bind', 'all'), sequence, func, add, 0) 1463 1464 def unbind_all(self, sequence): 1465 """Unbind for all widgets for event SEQUENCE all functions.""" 1466 self.tk.call('bind', 'all' , sequence, '') 1467 1468 def bind_class(self, className, sequence=None, func=None, add=None): 1469 """Bind to widgets with bindtag CLASSNAME at event 1470 SEQUENCE a call of function FUNC. An additional 1471 boolean parameter ADD specifies whether FUNC will be 1472 called additionally to the other bound function or 1473 whether it will replace the previous function. See bind for 1474 the return value.""" 1475 1476 return self._bind(('bind', className), sequence, func, add, 0) 1477 1478 def unbind_class(self, className, sequence): 1479 """Unbind for all widgets with bindtag CLASSNAME for event SEQUENCE 1480 all functions.""" 1481 self.tk.call('bind', className , sequence, '') 1482 1483 def mainloop(self, n=0): 1484 """Call the mainloop of Tk.""" 1485 self.tk.mainloop(n) 1486 1487 def quit(self): 1488 """Quit the Tcl interpreter. All widgets will be destroyed.""" 1489 self.tk.quit() 1490 1491 def _getints(self, string): 1492 """Internal function.""" 1493 if string: 1494 return tuple(map(self.tk.getint, self.tk.splitlist(string))) 1495 1496 def _getdoubles(self, string): 1497 """Internal function.""" 1498 if string: 1499 return tuple(map(self.tk.getdouble, self.tk.splitlist(string))) 1500 1501 def _getboolean(self, string): 1502 """Internal function.""" 1503 if string: 1504 return self.tk.getboolean(string) 1505 1506 def _displayof(self, displayof): 1507 """Internal function.""" 1508 if displayof: 1509 return ('-displayof', displayof) 1510 if displayof is None: 1511 return ('-displayof', self._w) 1512 return () 1513 1514 @property 1515 def _windowingsystem(self): 1516 """Internal function.""" 1517 try: 1518 return self._root()._windowingsystem_cached 1519 except AttributeError: 1520 ws = self._root()._windowingsystem_cached = \ 1521 self.tk.call('tk', 'windowingsystem') 1522 return ws 1523 1524 def _options(self, cnf, kw = None): 1525 """Internal function.""" 1526 if kw: 1527 cnf = _cnfmerge((cnf, kw)) 1528 else: 1529 cnf = _cnfmerge(cnf) 1530 res = () 1531 for k, v in cnf.items(): 1532 if v is not None: 1533 if k[-1] == '_': k = k[:-1] 1534 if callable(v): 1535 v = self._register(v) 1536 elif isinstance(v, (tuple, list)): 1537 nv = [] 1538 for item in v: 1539 if isinstance(item, int): 1540 nv.append(str(item)) 1541 elif isinstance(item, str): 1542 nv.append(_stringify(item)) 1543 else: 1544 break 1545 else: 1546 v = ' '.join(nv) 1547 res = res + ('-'+k, v) 1548 return res 1549 1550 def nametowidget(self, name): 1551 """Return the Tkinter instance of a widget identified by 1552 its Tcl name NAME.""" 1553 name = str(name).split('.') 1554 w = self 1555 1556 if not name[0]: 1557 w = w._root() 1558 name = name[1:] 1559 1560 for n in name: 1561 if not n: 1562 break 1563 w = w.children[n] 1564 1565 return w 1566 1567 _nametowidget = nametowidget 1568 1569 def _register(self, func, subst=None, needcleanup=1): 1570 """Return a newly created Tcl function. If this 1571 function is called, the Python function FUNC will 1572 be executed. An optional function SUBST can 1573 be given which will be executed before FUNC.""" 1574 f = CallWrapper(func, subst, self).__call__ 1575 name = repr(id(f)) 1576 try: 1577 func = func.__func__ 1578 except AttributeError: 1579 pass 1580 try: 1581 name = name + func.__name__ 1582 except AttributeError: 1583 pass 1584 self.tk.createcommand(name, f) 1585 if needcleanup: 1586 if self._tclCommands is None: 1587 self._tclCommands = [] 1588 self._tclCommands.append(name) 1589 return name 1590 1591 register = _register 1592 1593 def _root(self): 1594 """Internal function.""" 1595 w = self 1596 while w.master is not None: w = w.master 1597 return w 1598 _subst_format = ('%#', '%b', '%f', '%h', '%k', 1599 '%s', '%t', '%w', '%x', '%y', 1600 '%A', '%E', '%K', '%N', '%W', '%T', '%X', '%Y', '%D') 1601 _subst_format_str = " ".join(_subst_format) 1602 1603 def _substitute(self, *args): 1604 """Internal function.""" 1605 if len(args) != len(self._subst_format): return args 1606 getboolean = self.tk.getboolean 1607 1608 getint = self.tk.getint 1609 def getint_event(s): 1610 """Tk changed behavior in 8.4.2, returning "??" rather more often.""" 1611 try: 1612 return getint(s) 1613 except (ValueError, TclError): 1614 return s 1615 1616 nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args 1617 # Missing: (a, c, d, m, o, v, B, R) 1618 e = Event() 1619 # serial field: valid for all events 1620 # number of button: ButtonPress and ButtonRelease events only 1621 # height field: Configure, ConfigureRequest, Create, 1622 # ResizeRequest, and Expose events only 1623 # keycode field: KeyPress and KeyRelease events only 1624 # time field: "valid for events that contain a time field" 1625 # width field: Configure, ConfigureRequest, Create, ResizeRequest, 1626 # and Expose events only 1627 # x field: "valid for events that contain an x field" 1628 # y field: "valid for events that contain a y field" 1629 # keysym as decimal: KeyPress and KeyRelease events only 1630 # x_root, y_root fields: ButtonPress, ButtonRelease, KeyPress, 1631 # KeyRelease, and Motion events 1632 e.serial = getint(nsign) 1633 e.num = getint_event(b) 1634 try: e.focus = getboolean(f) 1635 except TclError: pass 1636 e.height = getint_event(h) 1637 e.keycode = getint_event(k) 1638 e.state = getint_event(s) 1639 e.time = getint_event(t) 1640 e.width = getint_event(w) 1641 e.x = getint_event(x) 1642 e.y = getint_event(y) 1643 e.char = A 1644 try: e.send_event = getboolean(E) 1645 except TclError: pass 1646 e.keysym = K 1647 e.keysym_num = getint_event(N) 1648 try: 1649 e.type = EventType(T) 1650 except ValueError: 1651 e.type = T 1652 try: 1653 e.widget = self._nametowidget(W) 1654 except KeyError: 1655 e.widget = W 1656 e.x_root = getint_event(X) 1657 e.y_root = getint_event(Y) 1658 try: 1659 e.delta = getint(D) 1660 except (ValueError, TclError): 1661 e.delta = 0 1662 return (e,) 1663 1664 def _report_exception(self): 1665 """Internal function.""" 1666 exc, val, tb = sys.exc_info() 1667 root = self._root() 1668 root.report_callback_exception(exc, val, tb) 1669 1670 def _getconfigure(self, *args): 1671 """Call Tcl configure command and return the result as a dict.""" 1672 cnf = {} 1673 for x in self.tk.splitlist(self.tk.call(*args)): 1674 x = self.tk.splitlist(x) 1675 cnf[x[0][1:]] = (x[0][1:],) + x[1:] 1676 return cnf 1677 1678 def _getconfigure1(self, *args): 1679 x = self.tk.splitlist(self.tk.call(*args)) 1680 return (x[0][1:],) + x[1:] 1681 1682 def _configure(self, cmd, cnf, kw): 1683 """Internal function.""" 1684 if kw: 1685 cnf = _cnfmerge((cnf, kw)) 1686 elif cnf: 1687 cnf = _cnfmerge(cnf) 1688 if cnf is None: 1689 return self._getconfigure(_flatten((self._w, cmd))) 1690 if isinstance(cnf, str): 1691 return self._getconfigure1(_flatten((self._w, cmd, '-'+cnf))) 1692 self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) 1693 # These used to be defined in Widget: 1694 1695 def configure(self, cnf=None, **kw): 1696 """Configure resources of a widget. 1697 1698 The values for resources are specified as keyword 1699 arguments. To get an overview about 1700 the allowed keyword arguments call the method keys. 1701 """ 1702 return self._configure('configure', cnf, kw) 1703 1704 config = configure 1705 1706 def cget(self, key): 1707 """Return the resource value for a KEY given as string.""" 1708 return self.tk.call(self._w, 'cget', '-' + key) 1709 1710 __getitem__ = cget 1711 1712 def __setitem__(self, key, value): 1713 self.configure({key: value}) 1714 1715 def keys(self): 1716 """Return a list of all resource names of this widget.""" 1717 splitlist = self.tk.splitlist 1718 return [splitlist(x)[0][1:] for x in 1719 splitlist(self.tk.call(self._w, 'configure'))] 1720 1721 def __str__(self): 1722 """Return the window path name of this widget.""" 1723 return self._w 1724 1725 def __repr__(self): 1726 return '<%s.%s object %s>' % ( 1727 self.__class__.__module__, self.__class__.__qualname__, self._w) 1728 1729 # Pack methods that apply to the master 1730 _noarg_ = ['_noarg_'] 1731 1732 def pack_propagate(self, flag=_noarg_): 1733 """Set or get the status for propagation of geometry information. 1734 1735 A boolean argument specifies whether the geometry information 1736 of the slaves will determine the size of this widget. If no argument 1737 is given the current setting will be returned. 1738 """ 1739 if flag is Misc._noarg_: 1740 return self._getboolean(self.tk.call( 1741 'pack', 'propagate', self._w)) 1742 else: 1743 self.tk.call('pack', 'propagate', self._w, flag) 1744 1745 propagate = pack_propagate 1746 1747 def pack_slaves(self): 1748 """Return a list of all slaves of this widget 1749 in its packing order.""" 1750 return [self._nametowidget(x) for x in 1751 self.tk.splitlist( 1752 self.tk.call('pack', 'slaves', self._w))] 1753 1754 slaves = pack_slaves 1755 1756 # Place method that applies to the master 1757 def place_slaves(self): 1758 """Return a list of all slaves of this widget 1759 in its packing order.""" 1760 return [self._nametowidget(x) for x in 1761 self.tk.splitlist( 1762 self.tk.call( 1763 'place', 'slaves', self._w))] 1764 1765 # Grid methods that apply to the master 1766 1767 def grid_anchor(self, anchor=None): # new in Tk 8.5 1768 """The anchor value controls how to place the grid within the 1769 master when no row/column has any weight. 1770 1771 The default anchor is nw.""" 1772 self.tk.call('grid', 'anchor', self._w, anchor) 1773 1774 anchor = grid_anchor 1775 1776 def grid_bbox(self, column=None, row=None, col2=None, row2=None): 1777 """Return a tuple of integer coordinates for the bounding 1778 box of this widget controlled by the geometry manager grid. 1779 1780 If COLUMN, ROW is given the bounding box applies from 1781 the cell with row and column 0 to the specified 1782 cell. If COL2 and ROW2 are given the bounding box 1783 starts at that cell. 1784 1785 The returned integers specify the offset of the upper left 1786 corner in the master widget and the width and height. 1787 """ 1788 args = ('grid', 'bbox', self._w) 1789 if column is not None and row is not None: 1790 args = args + (column, row) 1791 if col2 is not None and row2 is not None: 1792 args = args + (col2, row2) 1793 return self._getints(self.tk.call(*args)) or None 1794 1795 bbox = grid_bbox 1796 1797 def _gridconvvalue(self, value): 1798 if isinstance(value, (str, _tkinter.Tcl_Obj)): 1799 try: 1800 svalue = str(value) 1801 if not svalue: 1802 return None 1803 elif '.' in svalue: 1804 return self.tk.getdouble(svalue) 1805 else: 1806 return self.tk.getint(svalue) 1807 except (ValueError, TclError): 1808 pass 1809 return value 1810 1811 def _grid_configure(self, command, index, cnf, kw): 1812 """Internal function.""" 1813 if isinstance(cnf, str) and not kw: 1814 if cnf[-1:] == '_': 1815 cnf = cnf[:-1] 1816 if cnf[:1] != '-': 1817 cnf = '-'+cnf 1818 options = (cnf,) 1819 else: 1820 options = self._options(cnf, kw) 1821 if not options: 1822 return _splitdict( 1823 self.tk, 1824 self.tk.call('grid', command, self._w, index), 1825 conv=self._gridconvvalue) 1826 res = self.tk.call( 1827 ('grid', command, self._w, index) 1828 + options) 1829 if len(options) == 1: 1830 return self._gridconvvalue(res) 1831 1832 def grid_columnconfigure(self, index, cnf={}, **kw): 1833 """Configure column INDEX of a grid. 1834 1835 Valid resources are minsize (minimum size of the column), 1836 weight (how much does additional space propagate to this column) 1837 and pad (how much space to let additionally).""" 1838 return self._grid_configure('columnconfigure', index, cnf, kw) 1839 1840 columnconfigure = grid_columnconfigure 1841 1842 def grid_location(self, x, y): 1843 """Return a tuple of column and row which identify the cell 1844 at which the pixel at position X and Y inside the master 1845 widget is located.""" 1846 return self._getints( 1847 self.tk.call( 1848 'grid', 'location', self._w, x, y)) or None 1849 1850 def grid_propagate(self, flag=_noarg_): 1851 """Set or get the status for propagation of geometry information. 1852 1853 A boolean argument specifies whether the geometry information 1854 of the slaves will determine the size of this widget. If no argument 1855 is given, the current setting will be returned. 1856 """ 1857 if flag is Misc._noarg_: 1858 return self._getboolean(self.tk.call( 1859 'grid', 'propagate', self._w)) 1860 else: 1861 self.tk.call('grid', 'propagate', self._w, flag) 1862 1863 def grid_rowconfigure(self, index, cnf={}, **kw): 1864 """Configure row INDEX of a grid. 1865 1866 Valid resources are minsize (minimum size of the row), 1867 weight (how much does additional space propagate to this row) 1868 and pad (how much space to let additionally).""" 1869 return self._grid_configure('rowconfigure', index, cnf, kw) 1870 1871 rowconfigure = grid_rowconfigure 1872 1873 def grid_size(self): 1874 """Return a tuple of the number of column and rows in the grid.""" 1875 return self._getints( 1876 self.tk.call('grid', 'size', self._w)) or None 1877 1878 size = grid_size 1879 1880 def grid_slaves(self, row=None, column=None): 1881 """Return a list of all slaves of this widget 1882 in its packing order.""" 1883 args = () 1884 if row is not None: 1885 args = args + ('-row', row) 1886 if column is not None: 1887 args = args + ('-column', column) 1888 return [self._nametowidget(x) for x in 1889 self.tk.splitlist(self.tk.call( 1890 ('grid', 'slaves', self._w) + args))] 1891 1892 # Support for the "event" command, new in Tk 4.2. 1893 # By Case Roole. 1894 1895 def event_add(self, virtual, *sequences): 1896 """Bind a virtual event VIRTUAL (of the form <<Name>>) 1897 to an event SEQUENCE such that the virtual event is triggered 1898 whenever SEQUENCE occurs.""" 1899 args = ('event', 'add', virtual) + sequences 1900 self.tk.call(args) 1901 1902 def event_delete(self, virtual, *sequences): 1903 """Unbind a virtual event VIRTUAL from SEQUENCE.""" 1904 args = ('event', 'delete', virtual) + sequences 1905 self.tk.call(args) 1906 1907 def event_generate(self, sequence, **kw): 1908 """Generate an event SEQUENCE. Additional 1909 keyword arguments specify parameter of the event 1910 (e.g. x, y, rootx, rooty).""" 1911 args = ('event', 'generate', self._w, sequence) 1912 for k, v in kw.items(): 1913 args = args + ('-%s' % k, str(v)) 1914 self.tk.call(args) 1915 1916 def event_info(self, virtual=None): 1917 """Return a list of all virtual events or the information 1918 about the SEQUENCE bound to the virtual event VIRTUAL.""" 1919 return self.tk.splitlist( 1920 self.tk.call('event', 'info', virtual)) 1921 1922 # Image related commands 1923 1924 def image_names(self): 1925 """Return a list of all existing image names.""" 1926 return self.tk.splitlist(self.tk.call('image', 'names')) 1927 1928 def image_types(self): 1929 """Return a list of all available image types (e.g. photo bitmap).""" 1930 return self.tk.splitlist(self.tk.call('image', 'types')) 1931 1932 1933class CallWrapper: 1934 """Internal class. Stores function to call when some user 1935 defined Tcl function is called e.g. after an event occurred.""" 1936 1937 def __init__(self, func, subst, widget): 1938 """Store FUNC, SUBST and WIDGET as members.""" 1939 self.func = func 1940 self.subst = subst 1941 self.widget = widget 1942 1943 def __call__(self, *args): 1944 """Apply first function SUBST to arguments, than FUNC.""" 1945 try: 1946 if self.subst: 1947 args = self.subst(*args) 1948 return self.func(*args) 1949 except SystemExit: 1950 raise 1951 except: 1952 self.widget._report_exception() 1953 1954 1955class XView: 1956 """Mix-in class for querying and changing the horizontal position 1957 of a widget's window.""" 1958 1959 def xview(self, *args): 1960 """Query and change the horizontal position of the view.""" 1961 res = self.tk.call(self._w, 'xview', *args) 1962 if not args: 1963 return self._getdoubles(res) 1964 1965 def xview_moveto(self, fraction): 1966 """Adjusts the view in the window so that FRACTION of the 1967 total width of the canvas is off-screen to the left.""" 1968 self.tk.call(self._w, 'xview', 'moveto', fraction) 1969 1970 def xview_scroll(self, number, what): 1971 """Shift the x-view according to NUMBER which is measured in "units" 1972 or "pages" (WHAT).""" 1973 self.tk.call(self._w, 'xview', 'scroll', number, what) 1974 1975 1976class YView: 1977 """Mix-in class for querying and changing the vertical position 1978 of a widget's window.""" 1979 1980 def yview(self, *args): 1981 """Query and change the vertical position of the view.""" 1982 res = self.tk.call(self._w, 'yview', *args) 1983 if not args: 1984 return self._getdoubles(res) 1985 1986 def yview_moveto(self, fraction): 1987 """Adjusts the view in the window so that FRACTION of the 1988 total height of the canvas is off-screen to the top.""" 1989 self.tk.call(self._w, 'yview', 'moveto', fraction) 1990 1991 def yview_scroll(self, number, what): 1992 """Shift the y-view according to NUMBER which is measured in 1993 "units" or "pages" (WHAT).""" 1994 self.tk.call(self._w, 'yview', 'scroll', number, what) 1995 1996 1997class Wm: 1998 """Provides functions for the communication with the window manager.""" 1999 2000 def wm_aspect(self, 2001 minNumer=None, minDenom=None, 2002 maxNumer=None, maxDenom=None): 2003 """Instruct the window manager to set the aspect ratio (width/height) 2004 of this widget to be between MINNUMER/MINDENOM and MAXNUMER/MAXDENOM. Return a tuple 2005 of the actual values if no argument is given.""" 2006 return self._getints( 2007 self.tk.call('wm', 'aspect', self._w, 2008 minNumer, minDenom, 2009 maxNumer, maxDenom)) 2010 2011 aspect = wm_aspect 2012 2013 def wm_attributes(self, *args): 2014 """This subcommand returns or sets platform specific attributes 2015 2016 The first form returns a list of the platform specific flags and 2017 their values. The second form returns the value for the specific 2018 option. The third form sets one or more of the values. The values 2019 are as follows: 2020 2021 On Windows, -disabled gets or sets whether the window is in a 2022 disabled state. -toolwindow gets or sets the style of the window 2023 to toolwindow (as defined in the MSDN). -topmost gets or sets 2024 whether this is a topmost window (displays above all other 2025 windows). 2026 2027 On Macintosh, XXXXX 2028 2029 On Unix, there are currently no special attribute values. 2030 """ 2031 args = ('wm', 'attributes', self._w) + args 2032 return self.tk.call(args) 2033 2034 attributes = wm_attributes 2035 2036 def wm_client(self, name=None): 2037 """Store NAME in WM_CLIENT_MACHINE property of this widget. Return 2038 current value.""" 2039 return self.tk.call('wm', 'client', self._w, name) 2040 2041 client = wm_client 2042 2043 def wm_colormapwindows(self, *wlist): 2044 """Store list of window names (WLIST) into WM_COLORMAPWINDOWS property 2045 of this widget. This list contains windows whose colormaps differ from their 2046 parents. Return current list of widgets if WLIST is empty.""" 2047 if len(wlist) > 1: 2048 wlist = (wlist,) # Tk needs a list of windows here 2049 args = ('wm', 'colormapwindows', self._w) + wlist 2050 if wlist: 2051 self.tk.call(args) 2052 else: 2053 return [self._nametowidget(x) 2054 for x in self.tk.splitlist(self.tk.call(args))] 2055 2056 colormapwindows = wm_colormapwindows 2057 2058 def wm_command(self, value=None): 2059 """Store VALUE in WM_COMMAND property. It is the command 2060 which shall be used to invoke the application. Return current 2061 command if VALUE is None.""" 2062 return self.tk.call('wm', 'command', self._w, value) 2063 2064 command = wm_command 2065 2066 def wm_deiconify(self): 2067 """Deiconify this widget. If it was never mapped it will not be mapped. 2068 On Windows it will raise this widget and give it the focus.""" 2069 return self.tk.call('wm', 'deiconify', self._w) 2070 2071 deiconify = wm_deiconify 2072 2073 def wm_focusmodel(self, model=None): 2074 """Set focus model to MODEL. "active" means that this widget will claim 2075 the focus itself, "passive" means that the window manager shall give 2076 the focus. Return current focus model if MODEL is None.""" 2077 return self.tk.call('wm', 'focusmodel', self._w, model) 2078 2079 focusmodel = wm_focusmodel 2080 2081 def wm_forget(self, window): # new in Tk 8.5 2082 """The window will be unmapped from the screen and will no longer 2083 be managed by wm. toplevel windows will be treated like frame 2084 windows once they are no longer managed by wm, however, the menu 2085 option configuration will be remembered and the menus will return 2086 once the widget is managed again.""" 2087 self.tk.call('wm', 'forget', window) 2088 2089 forget = wm_forget 2090 2091 def wm_frame(self): 2092 """Return identifier for decorative frame of this widget if present.""" 2093 return self.tk.call('wm', 'frame', self._w) 2094 2095 frame = wm_frame 2096 2097 def wm_geometry(self, newGeometry=None): 2098 """Set geometry to NEWGEOMETRY of the form =widthxheight+x+y. Return 2099 current value if None is given.""" 2100 return self.tk.call('wm', 'geometry', self._w, newGeometry) 2101 2102 geometry = wm_geometry 2103 2104 def wm_grid(self, 2105 baseWidth=None, baseHeight=None, 2106 widthInc=None, heightInc=None): 2107 """Instruct the window manager that this widget shall only be 2108 resized on grid boundaries. WIDTHINC and HEIGHTINC are the width and 2109 height of a grid unit in pixels. BASEWIDTH and BASEHEIGHT are the 2110 number of grid units requested in Tk_GeometryRequest.""" 2111 return self._getints(self.tk.call( 2112 'wm', 'grid', self._w, 2113 baseWidth, baseHeight, widthInc, heightInc)) 2114 2115 grid = wm_grid 2116 2117 def wm_group(self, pathName=None): 2118 """Set the group leader widgets for related widgets to PATHNAME. Return 2119 the group leader of this widget if None is given.""" 2120 return self.tk.call('wm', 'group', self._w, pathName) 2121 2122 group = wm_group 2123 2124 def wm_iconbitmap(self, bitmap=None, default=None): 2125 """Set bitmap for the iconified widget to BITMAP. Return 2126 the bitmap if None is given. 2127 2128 Under Windows, the DEFAULT parameter can be used to set the icon 2129 for the widget and any descendants that don't have an icon set 2130 explicitly. DEFAULT can be the relative path to a .ico file 2131 (example: root.iconbitmap(default='myicon.ico') ). See Tk 2132 documentation for more information.""" 2133 if default: 2134 return self.tk.call('wm', 'iconbitmap', self._w, '-default', default) 2135 else: 2136 return self.tk.call('wm', 'iconbitmap', self._w, bitmap) 2137 2138 iconbitmap = wm_iconbitmap 2139 2140 def wm_iconify(self): 2141 """Display widget as icon.""" 2142 return self.tk.call('wm', 'iconify', self._w) 2143 2144 iconify = wm_iconify 2145 2146 def wm_iconmask(self, bitmap=None): 2147 """Set mask for the icon bitmap of this widget. Return the 2148 mask if None is given.""" 2149 return self.tk.call('wm', 'iconmask', self._w, bitmap) 2150 2151 iconmask = wm_iconmask 2152 2153 def wm_iconname(self, newName=None): 2154 """Set the name of the icon for this widget. Return the name if 2155 None is given.""" 2156 return self.tk.call('wm', 'iconname', self._w, newName) 2157 2158 iconname = wm_iconname 2159 2160 def wm_iconphoto(self, default=False, *args): # new in Tk 8.5 2161 """Sets the titlebar icon for this window based on the named photo 2162 images passed through args. If default is True, this is applied to 2163 all future created toplevels as well. 2164 2165 The data in the images is taken as a snapshot at the time of 2166 invocation. If the images are later changed, this is not reflected 2167 to the titlebar icons. Multiple images are accepted to allow 2168 different images sizes to be provided. The window manager may scale 2169 provided icons to an appropriate size. 2170 2171 On Windows, the images are packed into a Windows icon structure. 2172 This will override an icon specified to wm_iconbitmap, and vice 2173 versa. 2174 2175 On X, the images are arranged into the _NET_WM_ICON X property, 2176 which most modern window managers support. An icon specified by 2177 wm_iconbitmap may exist simultaneously. 2178 2179 On Macintosh, this currently does nothing.""" 2180 if default: 2181 self.tk.call('wm', 'iconphoto', self._w, "-default", *args) 2182 else: 2183 self.tk.call('wm', 'iconphoto', self._w, *args) 2184 2185 iconphoto = wm_iconphoto 2186 2187 def wm_iconposition(self, x=None, y=None): 2188 """Set the position of the icon of this widget to X and Y. Return 2189 a tuple of the current values of X and X if None is given.""" 2190 return self._getints(self.tk.call( 2191 'wm', 'iconposition', self._w, x, y)) 2192 2193 iconposition = wm_iconposition 2194 2195 def wm_iconwindow(self, pathName=None): 2196 """Set widget PATHNAME to be displayed instead of icon. Return the current 2197 value if None is given.""" 2198 return self.tk.call('wm', 'iconwindow', self._w, pathName) 2199 2200 iconwindow = wm_iconwindow 2201 2202 def wm_manage(self, widget): # new in Tk 8.5 2203 """The widget specified will become a stand alone top-level window. 2204 The window will be decorated with the window managers title bar, 2205 etc.""" 2206 self.tk.call('wm', 'manage', widget) 2207 2208 manage = wm_manage 2209 2210 def wm_maxsize(self, width=None, height=None): 2211 """Set max WIDTH and HEIGHT for this widget. If the window is gridded 2212 the values are given in grid units. Return the current values if None 2213 is given.""" 2214 return self._getints(self.tk.call( 2215 'wm', 'maxsize', self._w, width, height)) 2216 2217 maxsize = wm_maxsize 2218 2219 def wm_minsize(self, width=None, height=None): 2220 """Set min WIDTH and HEIGHT for this widget. If the window is gridded 2221 the values are given in grid units. Return the current values if None 2222 is given.""" 2223 return self._getints(self.tk.call( 2224 'wm', 'minsize', self._w, width, height)) 2225 2226 minsize = wm_minsize 2227 2228 def wm_overrideredirect(self, boolean=None): 2229 """Instruct the window manager to ignore this widget 2230 if BOOLEAN is given with 1. Return the current value if None 2231 is given.""" 2232 return self._getboolean(self.tk.call( 2233 'wm', 'overrideredirect', self._w, boolean)) 2234 2235 overrideredirect = wm_overrideredirect 2236 2237 def wm_positionfrom(self, who=None): 2238 """Instruct the window manager that the position of this widget shall 2239 be defined by the user if WHO is "user", and by its own policy if WHO is 2240 "program".""" 2241 return self.tk.call('wm', 'positionfrom', self._w, who) 2242 2243 positionfrom = wm_positionfrom 2244 2245 def wm_protocol(self, name=None, func=None): 2246 """Bind function FUNC to command NAME for this widget. 2247 Return the function bound to NAME if None is given. NAME could be 2248 e.g. "WM_SAVE_YOURSELF" or "WM_DELETE_WINDOW".""" 2249 if callable(func): 2250 command = self._register(func) 2251 else: 2252 command = func 2253 return self.tk.call( 2254 'wm', 'protocol', self._w, name, command) 2255 2256 protocol = wm_protocol 2257 2258 def wm_resizable(self, width=None, height=None): 2259 """Instruct the window manager whether this width can be resized 2260 in WIDTH or HEIGHT. Both values are boolean values.""" 2261 return self.tk.call('wm', 'resizable', self._w, width, height) 2262 2263 resizable = wm_resizable 2264 2265 def wm_sizefrom(self, who=None): 2266 """Instruct the window manager that the size of this widget shall 2267 be defined by the user if WHO is "user", and by its own policy if WHO is 2268 "program".""" 2269 return self.tk.call('wm', 'sizefrom', self._w, who) 2270 2271 sizefrom = wm_sizefrom 2272 2273 def wm_state(self, newstate=None): 2274 """Query or set the state of this widget as one of normal, icon, 2275 iconic (see wm_iconwindow), withdrawn, or zoomed (Windows only).""" 2276 return self.tk.call('wm', 'state', self._w, newstate) 2277 2278 state = wm_state 2279 2280 def wm_title(self, string=None): 2281 """Set the title of this widget.""" 2282 return self.tk.call('wm', 'title', self._w, string) 2283 2284 title = wm_title 2285 2286 def wm_transient(self, master=None): 2287 """Instruct the window manager that this widget is transient 2288 with regard to widget MASTER.""" 2289 return self.tk.call('wm', 'transient', self._w, master) 2290 2291 transient = wm_transient 2292 2293 def wm_withdraw(self): 2294 """Withdraw this widget from the screen such that it is unmapped 2295 and forgotten by the window manager. Re-draw it with wm_deiconify.""" 2296 return self.tk.call('wm', 'withdraw', self._w) 2297 2298 withdraw = wm_withdraw 2299 2300 2301class Tk(Misc, Wm): 2302 """Toplevel widget of Tk which represents mostly the main window 2303 of an application. It has an associated Tcl interpreter.""" 2304 _w = '.' 2305 2306 def __init__(self, screenName=None, baseName=None, className='Tk', 2307 useTk=True, sync=False, use=None): 2308 """Return a new top level widget on screen SCREENNAME. A new Tcl interpreter will 2309 be created. BASENAME will be used for the identification of the profile file (see 2310 readprofile). 2311 It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME 2312 is the name of the widget class.""" 2313 self.master = None 2314 self.children = {} 2315 self._tkloaded = False 2316 # to avoid recursions in the getattr code in case of failure, we 2317 # ensure that self.tk is always _something_. 2318 self.tk = None 2319 if baseName is None: 2320 import os 2321 baseName = os.path.basename(sys.argv[0]) 2322 baseName, ext = os.path.splitext(baseName) 2323 if ext not in ('.py', '.pyc'): 2324 baseName = baseName + ext 2325 interactive = False 2326 self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use) 2327 if useTk: 2328 self._loadtk() 2329 if not sys.flags.ignore_environment: 2330 # Issue #16248: Honor the -E flag to avoid code injection. 2331 self.readprofile(baseName, className) 2332 2333 def loadtk(self): 2334 if not self._tkloaded: 2335 self.tk.loadtk() 2336 self._loadtk() 2337 2338 def _loadtk(self): 2339 self._tkloaded = True 2340 global _default_root 2341 # Version sanity checks 2342 tk_version = self.tk.getvar('tk_version') 2343 if tk_version != _tkinter.TK_VERSION: 2344 raise RuntimeError("tk.h version (%s) doesn't match libtk.a version (%s)" 2345 % (_tkinter.TK_VERSION, tk_version)) 2346 # Under unknown circumstances, tcl_version gets coerced to float 2347 tcl_version = str(self.tk.getvar('tcl_version')) 2348 if tcl_version != _tkinter.TCL_VERSION: 2349 raise RuntimeError("tcl.h version (%s) doesn't match libtcl.a version (%s)" \ 2350 % (_tkinter.TCL_VERSION, tcl_version)) 2351 # Create and register the tkerror and exit commands 2352 # We need to inline parts of _register here, _ register 2353 # would register differently-named commands. 2354 if self._tclCommands is None: 2355 self._tclCommands = [] 2356 self.tk.createcommand('tkerror', _tkerror) 2357 self.tk.createcommand('exit', _exit) 2358 self._tclCommands.append('tkerror') 2359 self._tclCommands.append('exit') 2360 if _support_default_root and _default_root is None: 2361 _default_root = self 2362 self.protocol("WM_DELETE_WINDOW", self.destroy) 2363 2364 def destroy(self): 2365 """Destroy this and all descendants widgets. This will 2366 end the application of this Tcl interpreter.""" 2367 for c in list(self.children.values()): c.destroy() 2368 self.tk.call('destroy', self._w) 2369 Misc.destroy(self) 2370 global _default_root 2371 if _support_default_root and _default_root is self: 2372 _default_root = None 2373 2374 def readprofile(self, baseName, className): 2375 """Internal function. It reads .BASENAME.tcl and .CLASSNAME.tcl into 2376 the Tcl Interpreter and calls exec on the contents of .BASENAME.py and 2377 .CLASSNAME.py if such a file exists in the home directory.""" 2378 import os 2379 if 'HOME' in os.environ: home = os.environ['HOME'] 2380 else: home = os.curdir 2381 class_tcl = os.path.join(home, '.%s.tcl' % className) 2382 class_py = os.path.join(home, '.%s.py' % className) 2383 base_tcl = os.path.join(home, '.%s.tcl' % baseName) 2384 base_py = os.path.join(home, '.%s.py' % baseName) 2385 dir = {'self': self} 2386 exec('from tkinter import *', dir) 2387 if os.path.isfile(class_tcl): 2388 self.tk.call('source', class_tcl) 2389 if os.path.isfile(class_py): 2390 exec(open(class_py).read(), dir) 2391 if os.path.isfile(base_tcl): 2392 self.tk.call('source', base_tcl) 2393 if os.path.isfile(base_py): 2394 exec(open(base_py).read(), dir) 2395 2396 def report_callback_exception(self, exc, val, tb): 2397 """Report callback exception on sys.stderr. 2398 2399 Applications may want to override this internal function, and 2400 should when sys.stderr is None.""" 2401 import traceback 2402 print("Exception in Tkinter callback", file=sys.stderr) 2403 sys.last_type = exc 2404 sys.last_value = val 2405 sys.last_traceback = tb 2406 traceback.print_exception(exc, val, tb) 2407 2408 def __getattr__(self, attr): 2409 "Delegate attribute access to the interpreter object" 2410 return getattr(self.tk, attr) 2411 2412# Ideally, the classes Pack, Place and Grid disappear, the 2413# pack/place/grid methods are defined on the Widget class, and 2414# everybody uses w.pack_whatever(...) instead of Pack.whatever(w, 2415# ...), with pack(), place() and grid() being short for 2416# pack_configure(), place_configure() and grid_columnconfigure(), and 2417# forget() being short for pack_forget(). As a practical matter, I'm 2418# afraid that there is too much code out there that may be using the 2419# Pack, Place or Grid class, so I leave them intact -- but only as 2420# backwards compatibility features. Also note that those methods that 2421# take a master as argument (e.g. pack_propagate) have been moved to 2422# the Misc class (which now incorporates all methods common between 2423# toplevel and interior widgets). Again, for compatibility, these are 2424# copied into the Pack, Place or Grid class. 2425 2426 2427def Tcl(screenName=None, baseName=None, className='Tk', useTk=False): 2428 return Tk(screenName, baseName, className, useTk) 2429 2430 2431class Pack: 2432 """Geometry manager Pack. 2433 2434 Base class to use the methods pack_* in every widget.""" 2435 2436 def pack_configure(self, cnf={}, **kw): 2437 """Pack a widget in the parent widget. Use as options: 2438 after=widget - pack it after you have packed widget 2439 anchor=NSEW (or subset) - position widget according to 2440 given direction 2441 before=widget - pack it before you will pack widget 2442 expand=bool - expand widget if parent size grows 2443 fill=NONE or X or Y or BOTH - fill widget if widget grows 2444 in=master - use master to contain this widget 2445 in_=master - see 'in' option description 2446 ipadx=amount - add internal padding in x direction 2447 ipady=amount - add internal padding in y direction 2448 padx=amount - add padding in x direction 2449 pady=amount - add padding in y direction 2450 side=TOP or BOTTOM or LEFT or RIGHT - where to add this widget. 2451 """ 2452 self.tk.call( 2453 ('pack', 'configure', self._w) 2454 + self._options(cnf, kw)) 2455 2456 pack = configure = config = pack_configure 2457 2458 def pack_forget(self): 2459 """Unmap this widget and do not use it for the packing order.""" 2460 self.tk.call('pack', 'forget', self._w) 2461 2462 forget = pack_forget 2463 2464 def pack_info(self): 2465 """Return information about the packing options 2466 for this widget.""" 2467 d = _splitdict(self.tk, self.tk.call('pack', 'info', self._w)) 2468 if 'in' in d: 2469 d['in'] = self.nametowidget(d['in']) 2470 return d 2471 2472 info = pack_info 2473 propagate = pack_propagate = Misc.pack_propagate 2474 slaves = pack_slaves = Misc.pack_slaves 2475 2476 2477class Place: 2478 """Geometry manager Place. 2479 2480 Base class to use the methods place_* in every widget.""" 2481 2482 def place_configure(self, cnf={}, **kw): 2483 """Place a widget in the parent widget. Use as options: 2484 in=master - master relative to which the widget is placed 2485 in_=master - see 'in' option description 2486 x=amount - locate anchor of this widget at position x of master 2487 y=amount - locate anchor of this widget at position y of master 2488 relx=amount - locate anchor of this widget between 0.0 and 1.0 2489 relative to width of master (1.0 is right edge) 2490 rely=amount - locate anchor of this widget between 0.0 and 1.0 2491 relative to height of master (1.0 is bottom edge) 2492 anchor=NSEW (or subset) - position anchor according to given direction 2493 width=amount - width of this widget in pixel 2494 height=amount - height of this widget in pixel 2495 relwidth=amount - width of this widget between 0.0 and 1.0 2496 relative to width of master (1.0 is the same width 2497 as the master) 2498 relheight=amount - height of this widget between 0.0 and 1.0 2499 relative to height of master (1.0 is the same 2500 height as the master) 2501 bordermode="inside" or "outside" - whether to take border width of 2502 master widget into account 2503 """ 2504 self.tk.call( 2505 ('place', 'configure', self._w) 2506 + self._options(cnf, kw)) 2507 2508 place = configure = config = place_configure 2509 2510 def place_forget(self): 2511 """Unmap this widget.""" 2512 self.tk.call('place', 'forget', self._w) 2513 2514 forget = place_forget 2515 2516 def place_info(self): 2517 """Return information about the placing options 2518 for this widget.""" 2519 d = _splitdict(self.tk, self.tk.call('place', 'info', self._w)) 2520 if 'in' in d: 2521 d['in'] = self.nametowidget(d['in']) 2522 return d 2523 2524 info = place_info 2525 slaves = place_slaves = Misc.place_slaves 2526 2527 2528class Grid: 2529 """Geometry manager Grid. 2530 2531 Base class to use the methods grid_* in every widget.""" 2532 # Thanks to Masazumi Yoshikawa ([email protected]) 2533 2534 def grid_configure(self, cnf={}, **kw): 2535 """Position a widget in the parent widget in a grid. Use as options: 2536 column=number - use cell identified with given column (starting with 0) 2537 columnspan=number - this widget will span several columns 2538 in=master - use master to contain this widget 2539 in_=master - see 'in' option description 2540 ipadx=amount - add internal padding in x direction 2541 ipady=amount - add internal padding in y direction 2542 padx=amount - add padding in x direction 2543 pady=amount - add padding in y direction 2544 row=number - use cell identified with given row (starting with 0) 2545 rowspan=number - this widget will span several rows 2546 sticky=NSEW - if cell is larger on which sides will this 2547 widget stick to the cell boundary 2548 """ 2549 self.tk.call( 2550 ('grid', 'configure', self._w) 2551 + self._options(cnf, kw)) 2552 2553 grid = configure = config = grid_configure 2554 bbox = grid_bbox = Misc.grid_bbox 2555 columnconfigure = grid_columnconfigure = Misc.grid_columnconfigure 2556 2557 def grid_forget(self): 2558 """Unmap this widget.""" 2559 self.tk.call('grid', 'forget', self._w) 2560 2561 forget = grid_forget 2562 2563 def grid_remove(self): 2564 """Unmap this widget but remember the grid options.""" 2565 self.tk.call('grid', 'remove', self._w) 2566 2567 def grid_info(self): 2568 """Return information about the options 2569 for positioning this widget in a grid.""" 2570 d = _splitdict(self.tk, self.tk.call('grid', 'info', self._w)) 2571 if 'in' in d: 2572 d['in'] = self.nametowidget(d['in']) 2573 return d 2574 2575 info = grid_info 2576 location = grid_location = Misc.grid_location 2577 propagate = grid_propagate = Misc.grid_propagate 2578 rowconfigure = grid_rowconfigure = Misc.grid_rowconfigure 2579 size = grid_size = Misc.grid_size 2580 slaves = grid_slaves = Misc.grid_slaves 2581 2582 2583class BaseWidget(Misc): 2584 """Internal class.""" 2585 2586 def _setup(self, master, cnf): 2587 """Internal function. Sets up information about children.""" 2588 if master is None: 2589 master = _get_default_root() 2590 self.master = master 2591 self.tk = master.tk 2592 name = None 2593 if 'name' in cnf: 2594 name = cnf['name'] 2595 del cnf['name'] 2596 if not name: 2597 name = self.__class__.__name__.lower() 2598 if master._last_child_ids is None: 2599 master._last_child_ids = {} 2600 count = master._last_child_ids.get(name, 0) + 1 2601 master._last_child_ids[name] = count 2602 if count == 1: 2603 name = '!%s' % (name,) 2604 else: 2605 name = '!%s%d' % (name, count) 2606 self._name = name 2607 if master._w=='.': 2608 self._w = '.' + name 2609 else: 2610 self._w = master._w + '.' + name 2611 self.children = {} 2612 if self._name in self.master.children: 2613 self.master.children[self._name].destroy() 2614 self.master.children[self._name] = self 2615 2616 def __init__(self, master, widgetName, cnf={}, kw={}, extra=()): 2617 """Construct a widget with the parent widget MASTER, a name WIDGETNAME 2618 and appropriate options.""" 2619 if kw: 2620 cnf = _cnfmerge((cnf, kw)) 2621 self.widgetName = widgetName 2622 self._setup(master, cnf) 2623 if self._tclCommands is None: 2624 self._tclCommands = [] 2625 classes = [(k, v) for k, v in cnf.items() if isinstance(k, type)] 2626 for k, v in classes: 2627 del cnf[k] 2628 self.tk.call( 2629 (widgetName, self._w) + extra + self._options(cnf)) 2630 for k, v in classes: 2631 k.configure(self, v) 2632 2633 def destroy(self): 2634 """Destroy this and all descendants widgets.""" 2635 for c in list(self.children.values()): c.destroy() 2636 self.tk.call('destroy', self._w) 2637 if self._name in self.master.children: 2638 del self.master.children[self._name] 2639 Misc.destroy(self) 2640 2641 def _do(self, name, args=()): 2642 # XXX Obsolete -- better use self.tk.call directly! 2643 return self.tk.call((self._w, name) + args) 2644 2645 2646class Widget(BaseWidget, Pack, Place, Grid): 2647 """Internal class. 2648 2649 Base class for a widget which can be positioned with the geometry managers 2650 Pack, Place or Grid.""" 2651 pass 2652 2653 2654class Toplevel(BaseWidget, Wm): 2655 """Toplevel widget, e.g. for dialogs.""" 2656 2657 def __init__(self, master=None, cnf={}, **kw): 2658 """Construct a toplevel widget with the parent MASTER. 2659 2660 Valid resource names: background, bd, bg, borderwidth, class, 2661 colormap, container, cursor, height, highlightbackground, 2662 highlightcolor, highlightthickness, menu, relief, screen, takefocus, 2663 use, visual, width.""" 2664 if kw: 2665 cnf = _cnfmerge((cnf, kw)) 2666 extra = () 2667 for wmkey in ['screen', 'class_', 'class', 'visual', 2668 'colormap']: 2669 if wmkey in cnf: 2670 val = cnf[wmkey] 2671 # TBD: a hack needed because some keys 2672 # are not valid as keyword arguments 2673 if wmkey[-1] == '_': opt = '-'+wmkey[:-1] 2674 else: opt = '-'+wmkey 2675 extra = extra + (opt, val) 2676 del cnf[wmkey] 2677 BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra) 2678 root = self._root() 2679 self.iconname(root.iconname()) 2680 self.title(root.title()) 2681 self.protocol("WM_DELETE_WINDOW", self.destroy) 2682 2683 2684class Button(Widget): 2685 """Button widget.""" 2686 2687 def __init__(self, master=None, cnf={}, **kw): 2688 """Construct a button widget with the parent MASTER. 2689 2690 STANDARD OPTIONS 2691 2692 activebackground, activeforeground, anchor, 2693 background, bitmap, borderwidth, cursor, 2694 disabledforeground, font, foreground 2695 highlightbackground, highlightcolor, 2696 highlightthickness, image, justify, 2697 padx, pady, relief, repeatdelay, 2698 repeatinterval, takefocus, text, 2699 textvariable, underline, wraplength 2700 2701 WIDGET-SPECIFIC OPTIONS 2702 2703 command, compound, default, height, 2704 overrelief, state, width 2705 """ 2706 Widget.__init__(self, master, 'button', cnf, kw) 2707 2708 def flash(self): 2709 """Flash the button. 2710 2711 This is accomplished by redisplaying 2712 the button several times, alternating between active and 2713 normal colors. At the end of the flash the button is left 2714 in the same normal/active state as when the command was 2715 invoked. This command is ignored if the button's state is 2716 disabled. 2717 """ 2718 self.tk.call(self._w, 'flash') 2719 2720 def invoke(self): 2721 """Invoke the command associated with the button. 2722 2723 The return value is the return value from the command, 2724 or an empty string if there is no command associated with 2725 the button. This command is ignored if the button's state 2726 is disabled. 2727 """ 2728 return self.tk.call(self._w, 'invoke') 2729 2730 2731class Canvas(Widget, XView, YView): 2732 """Canvas widget to display graphical elements like lines or text.""" 2733 2734 def __init__(self, master=None, cnf={}, **kw): 2735 """Construct a canvas widget with the parent MASTER. 2736 2737 Valid resource names: background, bd, bg, borderwidth, closeenough, 2738 confine, cursor, height, highlightbackground, highlightcolor, 2739 highlightthickness, insertbackground, insertborderwidth, 2740 insertofftime, insertontime, insertwidth, offset, relief, 2741 scrollregion, selectbackground, selectborderwidth, selectforeground, 2742 state, takefocus, width, xscrollcommand, xscrollincrement, 2743 yscrollcommand, yscrollincrement.""" 2744 Widget.__init__(self, master, 'canvas', cnf, kw) 2745 2746 def addtag(self, *args): 2747 """Internal function.""" 2748 self.tk.call((self._w, 'addtag') + args) 2749 2750 def addtag_above(self, newtag, tagOrId): 2751 """Add tag NEWTAG to all items above TAGORID.""" 2752 self.addtag(newtag, 'above', tagOrId) 2753 2754 def addtag_all(self, newtag): 2755 """Add tag NEWTAG to all items.""" 2756 self.addtag(newtag, 'all') 2757 2758 def addtag_below(self, newtag, tagOrId): 2759 """Add tag NEWTAG to all items below TAGORID.""" 2760 self.addtag(newtag, 'below', tagOrId) 2761 2762 def addtag_closest(self, newtag, x, y, halo=None, start=None): 2763 """Add tag NEWTAG to item which is closest to pixel at X, Y. 2764 If several match take the top-most. 2765 All items closer than HALO are considered overlapping (all are 2766 closest). If START is specified the next below this tag is taken.""" 2767 self.addtag(newtag, 'closest', x, y, halo, start) 2768 2769 def addtag_enclosed(self, newtag, x1, y1, x2, y2): 2770 """Add tag NEWTAG to all items in the rectangle defined 2771 by X1,Y1,X2,Y2.""" 2772 self.addtag(newtag, 'enclosed', x1, y1, x2, y2) 2773 2774 def addtag_overlapping(self, newtag, x1, y1, x2, y2): 2775 """Add tag NEWTAG to all items which overlap the rectangle 2776 defined by X1,Y1,X2,Y2.""" 2777 self.addtag(newtag, 'overlapping', x1, y1, x2, y2) 2778 2779 def addtag_withtag(self, newtag, tagOrId): 2780 """Add tag NEWTAG to all items with TAGORID.""" 2781 self.addtag(newtag, 'withtag', tagOrId) 2782 2783 def bbox(self, *args): 2784 """Return a tuple of X1,Y1,X2,Y2 coordinates for a rectangle 2785 which encloses all items with tags specified as arguments.""" 2786 return self._getints( 2787 self.tk.call((self._w, 'bbox') + args)) or None 2788 2789 def tag_unbind(self, tagOrId, sequence, funcid=None): 2790 """Unbind for all items with TAGORID for event SEQUENCE the 2791 function identified with FUNCID.""" 2792 self.tk.call(self._w, 'bind', tagOrId, sequence, '') 2793 if funcid: 2794 self.deletecommand(funcid) 2795 2796 def tag_bind(self, tagOrId, sequence=None, func=None, add=None): 2797 """Bind to all items with TAGORID at event SEQUENCE a call to function FUNC. 2798 2799 An additional boolean parameter ADD specifies whether FUNC will be 2800 called additionally to the other bound function or whether it will 2801 replace the previous function. See bind for the return value.""" 2802 return self._bind((self._w, 'bind', tagOrId), 2803 sequence, func, add) 2804 2805 def canvasx(self, screenx, gridspacing=None): 2806 """Return the canvas x coordinate of pixel position SCREENX rounded 2807 to nearest multiple of GRIDSPACING units.""" 2808 return self.tk.getdouble(self.tk.call( 2809 self._w, 'canvasx', screenx, gridspacing)) 2810 2811 def canvasy(self, screeny, gridspacing=None): 2812 """Return the canvas y coordinate of pixel position SCREENY rounded 2813 to nearest multiple of GRIDSPACING units.""" 2814 return self.tk.getdouble(self.tk.call( 2815 self._w, 'canvasy', screeny, gridspacing)) 2816 2817 def coords(self, *args): 2818 """Return a list of coordinates for the item given in ARGS.""" 2819 # XXX Should use _flatten on args 2820 return [self.tk.getdouble(x) for x in 2821 self.tk.splitlist( 2822 self.tk.call((self._w, 'coords') + args))] 2823 2824 def _create(self, itemType, args, kw): # Args: (val, val, ..., cnf={}) 2825 """Internal function.""" 2826 args = _flatten(args) 2827 cnf = args[-1] 2828 if isinstance(cnf, (dict, tuple)): 2829 args = args[:-1] 2830 else: 2831 cnf = {} 2832 return self.tk.getint(self.tk.call( 2833 self._w, 'create', itemType, 2834 *(args + self._options(cnf, kw)))) 2835 2836 def create_arc(self, *args, **kw): 2837 """Create arc shaped region with coordinates x1,y1,x2,y2.""" 2838 return self._create('arc', args, kw) 2839 2840 def create_bitmap(self, *args, **kw): 2841 """Create bitmap with coordinates x1,y1.""" 2842 return self._create('bitmap', args, kw) 2843 2844 def create_image(self, *args, **kw): 2845 """Create image item with coordinates x1,y1.""" 2846 return self._create('image', args, kw) 2847 2848 def create_line(self, *args, **kw): 2849 """Create line with coordinates x1,y1,...,xn,yn.""" 2850 return self._create('line', args, kw) 2851 2852 def create_oval(self, *args, **kw): 2853 """Create oval with coordinates x1,y1,x2,y2.""" 2854 return self._create('oval', args, kw) 2855 2856 def create_polygon(self, *args, **kw): 2857 """Create polygon with coordinates x1,y1,...,xn,yn.""" 2858 return self._create('polygon', args, kw) 2859 2860 def create_rectangle(self, *args, **kw): 2861 """Create rectangle with coordinates x1,y1,x2,y2.""" 2862 return self._create('rectangle', args, kw) 2863 2864 def create_text(self, *args, **kw): 2865 """Create text with coordinates x1,y1.""" 2866 return self._create('text', args, kw) 2867 2868 def create_window(self, *args, **kw): 2869 """Create window with coordinates x1,y1,x2,y2.""" 2870 return self._create('window', args, kw) 2871 2872 def dchars(self, *args): 2873 """Delete characters of text items identified by tag or id in ARGS (possibly 2874 several times) from FIRST to LAST character (including).""" 2875 self.tk.call((self._w, 'dchars') + args) 2876 2877 def delete(self, *args): 2878 """Delete items identified by all tag or ids contained in ARGS.""" 2879 self.tk.call((self._w, 'delete') + args) 2880 2881 def dtag(self, *args): 2882 """Delete tag or id given as last arguments in ARGS from items 2883 identified by first argument in ARGS.""" 2884 self.tk.call((self._w, 'dtag') + args) 2885 2886 def find(self, *args): 2887 """Internal function.""" 2888 return self._getints( 2889 self.tk.call((self._w, 'find') + args)) or () 2890 2891 def find_above(self, tagOrId): 2892 """Return items above TAGORID.""" 2893 return self.find('above', tagOrId) 2894 2895 def find_all(self): 2896 """Return all items.""" 2897 return self.find('all') 2898 2899 def find_below(self, tagOrId): 2900 """Return all items below TAGORID.""" 2901 return self.find('below', tagOrId) 2902 2903 def find_closest(self, x, y, halo=None, start=None): 2904 """Return item which is closest to pixel at X, Y. 2905 If several match take the top-most. 2906 All items closer than HALO are considered overlapping (all are 2907 closest). If START is specified the next below this tag is taken.""" 2908 return self.find('closest', x, y, halo, start) 2909 2910 def find_enclosed(self, x1, y1, x2, y2): 2911 """Return all items in rectangle defined 2912 by X1,Y1,X2,Y2.""" 2913 return self.find('enclosed', x1, y1, x2, y2) 2914 2915 def find_overlapping(self, x1, y1, x2, y2): 2916 """Return all items which overlap the rectangle 2917 defined by X1,Y1,X2,Y2.""" 2918 return self.find('overlapping', x1, y1, x2, y2) 2919 2920 def find_withtag(self, tagOrId): 2921 """Return all items with TAGORID.""" 2922 return self.find('withtag', tagOrId) 2923 2924 def focus(self, *args): 2925 """Set focus to the first item specified in ARGS.""" 2926 return self.tk.call((self._w, 'focus') + args) 2927 2928 def gettags(self, *args): 2929 """Return tags associated with the first item specified in ARGS.""" 2930 return self.tk.splitlist( 2931 self.tk.call((self._w, 'gettags') + args)) 2932 2933 def icursor(self, *args): 2934 """Set cursor at position POS in the item identified by TAGORID. 2935 In ARGS TAGORID must be first.""" 2936 self.tk.call((self._w, 'icursor') + args) 2937 2938 def index(self, *args): 2939 """Return position of cursor as integer in item specified in ARGS.""" 2940 return self.tk.getint(self.tk.call((self._w, 'index') + args)) 2941 2942 def insert(self, *args): 2943 """Insert TEXT in item TAGORID at position POS. ARGS must 2944 be TAGORID POS TEXT.""" 2945 self.tk.call((self._w, 'insert') + args) 2946 2947 def itemcget(self, tagOrId, option): 2948 """Return the resource value for an OPTION for item TAGORID.""" 2949 return self.tk.call( 2950 (self._w, 'itemcget') + (tagOrId, '-'+option)) 2951 2952 def itemconfigure(self, tagOrId, cnf=None, **kw): 2953 """Configure resources of an item TAGORID. 2954 2955 The values for resources are specified as keyword 2956 arguments. To get an overview about 2957 the allowed keyword arguments call the method without arguments. 2958 """ 2959 return self._configure(('itemconfigure', tagOrId), cnf, kw) 2960 2961 itemconfig = itemconfigure 2962 2963 # lower, tkraise/lift hide Misc.lower, Misc.tkraise/lift, 2964 # so the preferred name for them is tag_lower, tag_raise 2965 # (similar to tag_bind, and similar to the Text widget); 2966 # unfortunately can't delete the old ones yet (maybe in 1.6) 2967 def tag_lower(self, *args): 2968 """Lower an item TAGORID given in ARGS 2969 (optional below another item).""" 2970 self.tk.call((self._w, 'lower') + args) 2971 2972 lower = tag_lower 2973 2974 def move(self, *args): 2975 """Move an item TAGORID given in ARGS.""" 2976 self.tk.call((self._w, 'move') + args) 2977 2978 def moveto(self, tagOrId, x='', y=''): 2979 """Move the items given by TAGORID in the canvas coordinate 2980 space so that the first coordinate pair of the bottommost 2981 item with tag TAGORID is located at position (X,Y). 2982 X and Y may be the empty string, in which case the 2983 corresponding coordinate will be unchanged. All items matching 2984 TAGORID remain in the same positions relative to each other.""" 2985 self.tk.call(self._w, 'moveto', tagOrId, x, y) 2986 2987 def postscript(self, cnf={}, **kw): 2988 """Print the contents of the canvas to a postscript 2989 file. Valid options: colormap, colormode, file, fontmap, 2990 height, pageanchor, pageheight, pagewidth, pagex, pagey, 2991 rotate, width, x, y.""" 2992 return self.tk.call((self._w, 'postscript') + 2993 self._options(cnf, kw)) 2994 2995 def tag_raise(self, *args): 2996 """Raise an item TAGORID given in ARGS 2997 (optional above another item).""" 2998 self.tk.call((self._w, 'raise') + args) 2999 3000 lift = tkraise = tag_raise 3001 3002 def scale(self, *args): 3003 """Scale item TAGORID with XORIGIN, YORIGIN, XSCALE, YSCALE.""" 3004 self.tk.call((self._w, 'scale') + args) 3005 3006 def scan_mark(self, x, y): 3007 """Remember the current X, Y coordinates.""" 3008 self.tk.call(self._w, 'scan', 'mark', x, y) 3009 3010 def scan_dragto(self, x, y, gain=10): 3011 """Adjust the view of the canvas to GAIN times the 3012 difference between X and Y and the coordinates given in 3013 scan_mark.""" 3014 self.tk.call(self._w, 'scan', 'dragto', x, y, gain) 3015 3016 def select_adjust(self, tagOrId, index): 3017 """Adjust the end of the selection near the cursor of an item TAGORID to index.""" 3018 self.tk.call(self._w, 'select', 'adjust', tagOrId, index) 3019 3020 def select_clear(self): 3021 """Clear the selection if it is in this widget.""" 3022 self.tk.call(self._w, 'select', 'clear') 3023 3024 def select_from(self, tagOrId, index): 3025 """Set the fixed end of a selection in item TAGORID to INDEX.""" 3026 self.tk.call(self._w, 'select', 'from', tagOrId, index) 3027 3028 def select_item(self): 3029 """Return the item which has the selection.""" 3030 return self.tk.call(self._w, 'select', 'item') or None 3031 3032 def select_to(self, tagOrId, index): 3033 """Set the variable end of a selection in item TAGORID to INDEX.""" 3034 self.tk.call(self._w, 'select', 'to', tagOrId, index) 3035 3036 def type(self, tagOrId): 3037 """Return the type of the item TAGORID.""" 3038 return self.tk.call(self._w, 'type', tagOrId) or None 3039 3040 3041_checkbutton_count = 0 3042 3043class Checkbutton(Widget): 3044 """Checkbutton widget which is either in on- or off-state.""" 3045 3046 def __init__(self, master=None, cnf={}, **kw): 3047 """Construct a checkbutton widget with the parent MASTER. 3048 3049 Valid resource names: activebackground, activeforeground, anchor, 3050 background, bd, bg, bitmap, borderwidth, command, cursor, 3051 disabledforeground, fg, font, foreground, height, 3052 highlightbackground, highlightcolor, highlightthickness, image, 3053 indicatoron, justify, offvalue, onvalue, padx, pady, relief, 3054 selectcolor, selectimage, state, takefocus, text, textvariable, 3055 underline, variable, width, wraplength.""" 3056 Widget.__init__(self, master, 'checkbutton', cnf, kw) 3057 3058 def _setup(self, master, cnf): 3059 if not cnf.get('name'): 3060 global _checkbutton_count 3061 name = self.__class__.__name__.lower() 3062 _checkbutton_count += 1 3063 cnf['name'] = f'!{name}{_checkbutton_count}' 3064 super()._setup(master, cnf) 3065 3066 def deselect(self): 3067 """Put the button in off-state.""" 3068 self.tk.call(self._w, 'deselect') 3069 3070 def flash(self): 3071 """Flash the button.""" 3072 self.tk.call(self._w, 'flash') 3073 3074 def invoke(self): 3075 """Toggle the button and invoke a command if given as resource.""" 3076 return self.tk.call(self._w, 'invoke') 3077 3078 def select(self): 3079 """Put the button in on-state.""" 3080 self.tk.call(self._w, 'select') 3081 3082 def toggle(self): 3083 """Toggle the button.""" 3084 self.tk.call(self._w, 'toggle') 3085 3086 3087class Entry(Widget, XView): 3088 """Entry widget which allows displaying simple text.""" 3089 3090 def __init__(self, master=None, cnf={}, **kw): 3091 """Construct an entry widget with the parent MASTER. 3092 3093 Valid resource names: background, bd, bg, borderwidth, cursor, 3094 exportselection, fg, font, foreground, highlightbackground, 3095 highlightcolor, highlightthickness, insertbackground, 3096 insertborderwidth, insertofftime, insertontime, insertwidth, 3097 invalidcommand, invcmd, justify, relief, selectbackground, 3098 selectborderwidth, selectforeground, show, state, takefocus, 3099 textvariable, validate, validatecommand, vcmd, width, 3100 xscrollcommand.""" 3101 Widget.__init__(self, master, 'entry', cnf, kw) 3102 3103 def delete(self, first, last=None): 3104 """Delete text from FIRST to LAST (not included).""" 3105 self.tk.call(self._w, 'delete', first, last) 3106 3107 def get(self): 3108 """Return the text.""" 3109 return self.tk.call(self._w, 'get') 3110 3111 def icursor(self, index): 3112 """Insert cursor at INDEX.""" 3113 self.tk.call(self._w, 'icursor', index) 3114 3115 def index(self, index): 3116 """Return position of cursor.""" 3117 return self.tk.getint(self.tk.call( 3118 self._w, 'index', index)) 3119 3120 def insert(self, index, string): 3121 """Insert STRING at INDEX.""" 3122 self.tk.call(self._w, 'insert', index, string) 3123 3124 def scan_mark(self, x): 3125 """Remember the current X, Y coordinates.""" 3126 self.tk.call(self._w, 'scan', 'mark', x) 3127 3128 def scan_dragto(self, x): 3129 """Adjust the view of the canvas to 10 times the 3130 difference between X and Y and the coordinates given in 3131 scan_mark.""" 3132 self.tk.call(self._w, 'scan', 'dragto', x) 3133 3134 def selection_adjust(self, index): 3135 """Adjust the end of the selection near the cursor to INDEX.""" 3136 self.tk.call(self._w, 'selection', 'adjust', index) 3137 3138 select_adjust = selection_adjust 3139 3140 def selection_clear(self): 3141 """Clear the selection if it is in this widget.""" 3142 self.tk.call(self._w, 'selection', 'clear') 3143 3144 select_clear = selection_clear 3145 3146 def selection_from(self, index): 3147 """Set the fixed end of a selection to INDEX.""" 3148 self.tk.call(self._w, 'selection', 'from', index) 3149 3150 select_from = selection_from 3151 3152 def selection_present(self): 3153 """Return True if there are characters selected in the entry, False 3154 otherwise.""" 3155 return self.tk.getboolean( 3156 self.tk.call(self._w, 'selection', 'present')) 3157 3158 select_present = selection_present 3159 3160 def selection_range(self, start, end): 3161 """Set the selection from START to END (not included).""" 3162 self.tk.call(self._w, 'selection', 'range', start, end) 3163 3164 select_range = selection_range 3165 3166 def selection_to(self, index): 3167 """Set the variable end of a selection to INDEX.""" 3168 self.tk.call(self._w, 'selection', 'to', index) 3169 3170 select_to = selection_to 3171 3172 3173class Frame(Widget): 3174 """Frame widget which may contain other widgets and can have a 3D border.""" 3175 3176 def __init__(self, master=None, cnf={}, **kw): 3177 """Construct a frame widget with the parent MASTER. 3178 3179 Valid resource names: background, bd, bg, borderwidth, class, 3180 colormap, container, cursor, height, highlightbackground, 3181 highlightcolor, highlightthickness, relief, takefocus, visual, width.""" 3182 cnf = _cnfmerge((cnf, kw)) 3183 extra = () 3184 if 'class_' in cnf: 3185 extra = ('-class', cnf['class_']) 3186 del cnf['class_'] 3187 elif 'class' in cnf: 3188 extra = ('-class', cnf['class']) 3189 del cnf['class'] 3190 Widget.__init__(self, master, 'frame', cnf, {}, extra) 3191 3192 3193class Label(Widget): 3194 """Label widget which can display text and bitmaps.""" 3195 3196 def __init__(self, master=None, cnf={}, **kw): 3197 """Construct a label widget with the parent MASTER. 3198 3199 STANDARD OPTIONS 3200 3201 activebackground, activeforeground, anchor, 3202 background, bitmap, borderwidth, cursor, 3203 disabledforeground, font, foreground, 3204 highlightbackground, highlightcolor, 3205 highlightthickness, image, justify, 3206 padx, pady, relief, takefocus, text, 3207 textvariable, underline, wraplength 3208 3209 WIDGET-SPECIFIC OPTIONS 3210 3211 height, state, width 3212 3213 """ 3214 Widget.__init__(self, master, 'label', cnf, kw) 3215 3216 3217class Listbox(Widget, XView, YView): 3218 """Listbox widget which can display a list of strings.""" 3219 3220 def __init__(self, master=None, cnf={}, **kw): 3221 """Construct a listbox widget with the parent MASTER. 3222 3223 Valid resource names: background, bd, bg, borderwidth, cursor, 3224 exportselection, fg, font, foreground, height, highlightbackground, 3225 highlightcolor, highlightthickness, relief, selectbackground, 3226 selectborderwidth, selectforeground, selectmode, setgrid, takefocus, 3227 width, xscrollcommand, yscrollcommand, listvariable.""" 3228 Widget.__init__(self, master, 'listbox', cnf, kw) 3229 3230 def activate(self, index): 3231 """Activate item identified by INDEX.""" 3232 self.tk.call(self._w, 'activate', index) 3233 3234 def bbox(self, index): 3235 """Return a tuple of X1,Y1,X2,Y2 coordinates for a rectangle 3236 which encloses the item identified by the given index.""" 3237 return self._getints(self.tk.call(self._w, 'bbox', index)) or None 3238 3239 def curselection(self): 3240 """Return the indices of currently selected item.""" 3241 return self._getints(self.tk.call(self._w, 'curselection')) or () 3242 3243 def delete(self, first, last=None): 3244 """Delete items from FIRST to LAST (included).""" 3245 self.tk.call(self._w, 'delete', first, last) 3246 3247 def get(self, first, last=None): 3248 """Get list of items from FIRST to LAST (included).""" 3249 if last is not None: 3250 return self.tk.splitlist(self.tk.call( 3251 self._w, 'get', first, last)) 3252 else: 3253 return self.tk.call(self._w, 'get', first) 3254 3255 def index(self, index): 3256 """Return index of item identified with INDEX.""" 3257 i = self.tk.call(self._w, 'index', index) 3258 if i == 'none': return None 3259 return self.tk.getint(i) 3260 3261 def insert(self, index, *elements): 3262 """Insert ELEMENTS at INDEX.""" 3263 self.tk.call((self._w, 'insert', index) + elements) 3264 3265 def nearest(self, y): 3266 """Get index of item which is nearest to y coordinate Y.""" 3267 return self.tk.getint(self.tk.call( 3268 self._w, 'nearest', y)) 3269 3270 def scan_mark(self, x, y): 3271 """Remember the current X, Y coordinates.""" 3272 self.tk.call(self._w, 'scan', 'mark', x, y) 3273 3274 def scan_dragto(self, x, y): 3275 """Adjust the view of the listbox to 10 times the 3276 difference between X and Y and the coordinates given in 3277 scan_mark.""" 3278 self.tk.call(self._w, 'scan', 'dragto', x, y) 3279 3280 def see(self, index): 3281 """Scroll such that INDEX is visible.""" 3282 self.tk.call(self._w, 'see', index) 3283 3284 def selection_anchor(self, index): 3285 """Set the fixed end oft the selection to INDEX.""" 3286 self.tk.call(self._w, 'selection', 'anchor', index) 3287 3288 select_anchor = selection_anchor 3289 3290 def selection_clear(self, first, last=None): 3291 """Clear the selection from FIRST to LAST (included).""" 3292 self.tk.call(self._w, 3293 'selection', 'clear', first, last) 3294 3295 select_clear = selection_clear 3296 3297 def selection_includes(self, index): 3298 """Return True if INDEX is part of the selection.""" 3299 return self.tk.getboolean(self.tk.call( 3300 self._w, 'selection', 'includes', index)) 3301 3302 select_includes = selection_includes 3303 3304 def selection_set(self, first, last=None): 3305 """Set the selection from FIRST to LAST (included) without 3306 changing the currently selected elements.""" 3307 self.tk.call(self._w, 'selection', 'set', first, last) 3308 3309 select_set = selection_set 3310 3311 def size(self): 3312 """Return the number of elements in the listbox.""" 3313 return self.tk.getint(self.tk.call(self._w, 'size')) 3314 3315 def itemcget(self, index, option): 3316 """Return the resource value for an ITEM and an OPTION.""" 3317 return self.tk.call( 3318 (self._w, 'itemcget') + (index, '-'+option)) 3319 3320 def itemconfigure(self, index, cnf=None, **kw): 3321 """Configure resources of an ITEM. 3322 3323 The values for resources are specified as keyword arguments. 3324 To get an overview about the allowed keyword arguments 3325 call the method without arguments. 3326 Valid resource names: background, bg, foreground, fg, 3327 selectbackground, selectforeground.""" 3328 return self._configure(('itemconfigure', index), cnf, kw) 3329 3330 itemconfig = itemconfigure 3331 3332 3333class Menu(Widget): 3334 """Menu widget which allows displaying menu bars, pull-down menus and pop-up menus.""" 3335 3336 def __init__(self, master=None, cnf={}, **kw): 3337 """Construct menu widget with the parent MASTER. 3338 3339 Valid resource names: activebackground, activeborderwidth, 3340 activeforeground, background, bd, bg, borderwidth, cursor, 3341 disabledforeground, fg, font, foreground, postcommand, relief, 3342 selectcolor, takefocus, tearoff, tearoffcommand, title, type.""" 3343 Widget.__init__(self, master, 'menu', cnf, kw) 3344 3345 def tk_popup(self, x, y, entry=""): 3346 """Post the menu at position X,Y with entry ENTRY.""" 3347 self.tk.call('tk_popup', self._w, x, y, entry) 3348 3349 def activate(self, index): 3350 """Activate entry at INDEX.""" 3351 self.tk.call(self._w, 'activate', index) 3352 3353 def add(self, itemType, cnf={}, **kw): 3354 """Internal function.""" 3355 self.tk.call((self._w, 'add', itemType) + 3356 self._options(cnf, kw)) 3357 3358 def add_cascade(self, cnf={}, **kw): 3359 """Add hierarchical menu item.""" 3360 self.add('cascade', cnf or kw) 3361 3362 def add_checkbutton(self, cnf={}, **kw): 3363 """Add checkbutton menu item.""" 3364 self.add('checkbutton', cnf or kw) 3365 3366 def add_command(self, cnf={}, **kw): 3367 """Add command menu item.""" 3368 self.add('command', cnf or kw) 3369 3370 def add_radiobutton(self, cnf={}, **kw): 3371 """Add radio menu item.""" 3372 self.add('radiobutton', cnf or kw) 3373 3374 def add_separator(self, cnf={}, **kw): 3375 """Add separator.""" 3376 self.add('separator', cnf or kw) 3377 3378 def insert(self, index, itemType, cnf={}, **kw): 3379 """Internal function.""" 3380 self.tk.call((self._w, 'insert', index, itemType) + 3381 self._options(cnf, kw)) 3382 3383 def insert_cascade(self, index, cnf={}, **kw): 3384 """Add hierarchical menu item at INDEX.""" 3385 self.insert(index, 'cascade', cnf or kw) 3386 3387 def insert_checkbutton(self, index, cnf={}, **kw): 3388 """Add checkbutton menu item at INDEX.""" 3389 self.insert(index, 'checkbutton', cnf or kw) 3390 3391 def insert_command(self, index, cnf={}, **kw): 3392 """Add command menu item at INDEX.""" 3393 self.insert(index, 'command', cnf or kw) 3394 3395 def insert_radiobutton(self, index, cnf={}, **kw): 3396 """Add radio menu item at INDEX.""" 3397 self.insert(index, 'radiobutton', cnf or kw) 3398 3399 def insert_separator(self, index, cnf={}, **kw): 3400 """Add separator at INDEX.""" 3401 self.insert(index, 'separator', cnf or kw) 3402 3403 def delete(self, index1, index2=None): 3404 """Delete menu items between INDEX1 and INDEX2 (included).""" 3405 if index2 is None: 3406 index2 = index1 3407 3408 num_index1, num_index2 = self.index(index1), self.index(index2) 3409 if (num_index1 is None) or (num_index2 is None): 3410 num_index1, num_index2 = 0, -1 3411 3412 for i in range(num_index1, num_index2 + 1): 3413 if 'command' in self.entryconfig(i): 3414 c = str(self.entrycget(i, 'command')) 3415 if c: 3416 self.deletecommand(c) 3417 self.tk.call(self._w, 'delete', index1, index2) 3418 3419 def entrycget(self, index, option): 3420 """Return the resource value of a menu item for OPTION at INDEX.""" 3421 return self.tk.call(self._w, 'entrycget', index, '-' + option) 3422 3423 def entryconfigure(self, index, cnf=None, **kw): 3424 """Configure a menu item at INDEX.""" 3425 return self._configure(('entryconfigure', index), cnf, kw) 3426 3427 entryconfig = entryconfigure 3428 3429 def index(self, index): 3430 """Return the index of a menu item identified by INDEX.""" 3431 i = self.tk.call(self._w, 'index', index) 3432 return None if i in ('', 'none') else self.tk.getint(i) # GH-103685. 3433 3434 def invoke(self, index): 3435 """Invoke a menu item identified by INDEX and execute 3436 the associated command.""" 3437 return self.tk.call(self._w, 'invoke', index) 3438 3439 def post(self, x, y): 3440 """Display a menu at position X,Y.""" 3441 self.tk.call(self._w, 'post', x, y) 3442 3443 def type(self, index): 3444 """Return the type of the menu item at INDEX.""" 3445 return self.tk.call(self._w, 'type', index) 3446 3447 def unpost(self): 3448 """Unmap a menu.""" 3449 self.tk.call(self._w, 'unpost') 3450 3451 def xposition(self, index): # new in Tk 8.5 3452 """Return the x-position of the leftmost pixel of the menu item 3453 at INDEX.""" 3454 return self.tk.getint(self.tk.call(self._w, 'xposition', index)) 3455 3456 def yposition(self, index): 3457 """Return the y-position of the topmost pixel of the menu item at INDEX.""" 3458 return self.tk.getint(self.tk.call( 3459 self._w, 'yposition', index)) 3460 3461 3462class Menubutton(Widget): 3463 """Menubutton widget, obsolete since Tk8.0.""" 3464 3465 def __init__(self, master=None, cnf={}, **kw): 3466 Widget.__init__(self, master, 'menubutton', cnf, kw) 3467 3468 3469class Message(Widget): 3470 """Message widget to display multiline text. Obsolete since Label does it too.""" 3471 3472 def __init__(self, master=None, cnf={}, **kw): 3473 Widget.__init__(self, master, 'message', cnf, kw) 3474 3475 3476class Radiobutton(Widget): 3477 """Radiobutton widget which shows only one of several buttons in on-state.""" 3478 3479 def __init__(self, master=None, cnf={}, **kw): 3480 """Construct a radiobutton widget with the parent MASTER. 3481 3482 Valid resource names: activebackground, activeforeground, anchor, 3483 background, bd, bg, bitmap, borderwidth, command, cursor, 3484 disabledforeground, fg, font, foreground, height, 3485 highlightbackground, highlightcolor, highlightthickness, image, 3486 indicatoron, justify, padx, pady, relief, selectcolor, selectimage, 3487 state, takefocus, text, textvariable, underline, value, variable, 3488 width, wraplength.""" 3489 Widget.__init__(self, master, 'radiobutton', cnf, kw) 3490 3491 def deselect(self): 3492 """Put the button in off-state.""" 3493 3494 self.tk.call(self._w, 'deselect') 3495 3496 def flash(self): 3497 """Flash the button.""" 3498 self.tk.call(self._w, 'flash') 3499 3500 def invoke(self): 3501 """Toggle the button and invoke a command if given as resource.""" 3502 return self.tk.call(self._w, 'invoke') 3503 3504 def select(self): 3505 """Put the button in on-state.""" 3506 self.tk.call(self._w, 'select') 3507 3508 3509class Scale(Widget): 3510 """Scale widget which can display a numerical scale.""" 3511 3512 def __init__(self, master=None, cnf={}, **kw): 3513 """Construct a scale widget with the parent MASTER. 3514 3515 Valid resource names: activebackground, background, bigincrement, bd, 3516 bg, borderwidth, command, cursor, digits, fg, font, foreground, from, 3517 highlightbackground, highlightcolor, highlightthickness, label, 3518 length, orient, relief, repeatdelay, repeatinterval, resolution, 3519 showvalue, sliderlength, sliderrelief, state, takefocus, 3520 tickinterval, to, troughcolor, variable, width.""" 3521 Widget.__init__(self, master, 'scale', cnf, kw) 3522 3523 def get(self): 3524 """Get the current value as integer or float.""" 3525 value = self.tk.call(self._w, 'get') 3526 try: 3527 return self.tk.getint(value) 3528 except (ValueError, TypeError, TclError): 3529 return self.tk.getdouble(value) 3530 3531 def set(self, value): 3532 """Set the value to VALUE.""" 3533 self.tk.call(self._w, 'set', value) 3534 3535 def coords(self, value=None): 3536 """Return a tuple (X,Y) of the point along the centerline of the 3537 trough that corresponds to VALUE or the current value if None is 3538 given.""" 3539 3540 return self._getints(self.tk.call(self._w, 'coords', value)) 3541 3542 def identify(self, x, y): 3543 """Return where the point X,Y lies. Valid return values are "slider", 3544 "though1" and "though2".""" 3545 return self.tk.call(self._w, 'identify', x, y) 3546 3547 3548class Scrollbar(Widget): 3549 """Scrollbar widget which displays a slider at a certain position.""" 3550 3551 def __init__(self, master=None, cnf={}, **kw): 3552 """Construct a scrollbar widget with the parent MASTER. 3553 3554 Valid resource names: activebackground, activerelief, 3555 background, bd, bg, borderwidth, command, cursor, 3556 elementborderwidth, highlightbackground, 3557 highlightcolor, highlightthickness, jump, orient, 3558 relief, repeatdelay, repeatinterval, takefocus, 3559 troughcolor, width.""" 3560 Widget.__init__(self, master, 'scrollbar', cnf, kw) 3561 3562 def activate(self, index=None): 3563 """Marks the element indicated by index as active. 3564 The only index values understood by this method are "arrow1", 3565 "slider", or "arrow2". If any other value is specified then no 3566 element of the scrollbar will be active. If index is not specified, 3567 the method returns the name of the element that is currently active, 3568 or None if no element is active.""" 3569 return self.tk.call(self._w, 'activate', index) or None 3570 3571 def delta(self, deltax, deltay): 3572 """Return the fractional change of the scrollbar setting if it 3573 would be moved by DELTAX or DELTAY pixels.""" 3574 return self.tk.getdouble( 3575 self.tk.call(self._w, 'delta', deltax, deltay)) 3576 3577 def fraction(self, x, y): 3578 """Return the fractional value which corresponds to a slider 3579 position of X,Y.""" 3580 return self.tk.getdouble(self.tk.call(self._w, 'fraction', x, y)) 3581 3582 def identify(self, x, y): 3583 """Return the element under position X,Y as one of 3584 "arrow1","slider","arrow2" or "".""" 3585 return self.tk.call(self._w, 'identify', x, y) 3586 3587 def get(self): 3588 """Return the current fractional values (upper and lower end) 3589 of the slider position.""" 3590 return self._getdoubles(self.tk.call(self._w, 'get')) 3591 3592 def set(self, first, last): 3593 """Set the fractional values of the slider position (upper and 3594 lower ends as value between 0 and 1).""" 3595 self.tk.call(self._w, 'set', first, last) 3596 3597 3598class Text(Widget, XView, YView): 3599 """Text widget which can display text in various forms.""" 3600 3601 def __init__(self, master=None, cnf={}, **kw): 3602 """Construct a text widget with the parent MASTER. 3603 3604 STANDARD OPTIONS 3605 3606 background, borderwidth, cursor, 3607 exportselection, font, foreground, 3608 highlightbackground, highlightcolor, 3609 highlightthickness, insertbackground, 3610 insertborderwidth, insertofftime, 3611 insertontime, insertwidth, padx, pady, 3612 relief, selectbackground, 3613 selectborderwidth, selectforeground, 3614 setgrid, takefocus, 3615 xscrollcommand, yscrollcommand, 3616 3617 WIDGET-SPECIFIC OPTIONS 3618 3619 autoseparators, height, maxundo, 3620 spacing1, spacing2, spacing3, 3621 state, tabs, undo, width, wrap, 3622 3623 """ 3624 Widget.__init__(self, master, 'text', cnf, kw) 3625 3626 def bbox(self, index): 3627 """Return a tuple of (x,y,width,height) which gives the bounding 3628 box of the visible part of the character at the given index.""" 3629 return self._getints( 3630 self.tk.call(self._w, 'bbox', index)) or None 3631 3632 def compare(self, index1, op, index2): 3633 """Return whether between index INDEX1 and index INDEX2 the 3634 relation OP is satisfied. OP is one of <, <=, ==, >=, >, or !=.""" 3635 return self.tk.getboolean(self.tk.call( 3636 self._w, 'compare', index1, op, index2)) 3637 3638 def count(self, index1, index2, *args): # new in Tk 8.5 3639 """Counts the number of relevant things between the two indices. 3640 If index1 is after index2, the result will be a negative number 3641 (and this holds for each of the possible options). 3642 3643 The actual items which are counted depends on the options given by 3644 args. The result is a list of integers, one for the result of each 3645 counting option given. Valid counting options are "chars", 3646 "displaychars", "displayindices", "displaylines", "indices", 3647 "lines", "xpixels" and "ypixels". There is an additional possible 3648 option "update", which if given then all subsequent options ensure 3649 that any possible out of date information is recalculated.""" 3650 args = ['-%s' % arg for arg in args] 3651 args += [index1, index2] 3652 res = self.tk.call(self._w, 'count', *args) or None 3653 if res is not None and len(args) <= 3: 3654 return (res, ) 3655 else: 3656 return res 3657 3658 def debug(self, boolean=None): 3659 """Turn on the internal consistency checks of the B-Tree inside the text 3660 widget according to BOOLEAN.""" 3661 if boolean is None: 3662 return self.tk.getboolean(self.tk.call(self._w, 'debug')) 3663 self.tk.call(self._w, 'debug', boolean) 3664 3665 def delete(self, index1, index2=None): 3666 """Delete the characters between INDEX1 and INDEX2 (not included).""" 3667 self.tk.call(self._w, 'delete', index1, index2) 3668 3669 def dlineinfo(self, index): 3670 """Return tuple (x,y,width,height,baseline) giving the bounding box 3671 and baseline position of the visible part of the line containing 3672 the character at INDEX.""" 3673 return self._getints(self.tk.call(self._w, 'dlineinfo', index)) 3674 3675 def dump(self, index1, index2=None, command=None, **kw): 3676 """Return the contents of the widget between index1 and index2. 3677 3678 The type of contents returned in filtered based on the keyword 3679 parameters; if 'all', 'image', 'mark', 'tag', 'text', or 'window' are 3680 given and true, then the corresponding items are returned. The result 3681 is a list of triples of the form (key, value, index). If none of the 3682 keywords are true then 'all' is used by default. 3683 3684 If the 'command' argument is given, it is called once for each element 3685 of the list of triples, with the values of each triple serving as the 3686 arguments to the function. In this case the list is not returned.""" 3687 args = [] 3688 func_name = None 3689 result = None 3690 if not command: 3691 # Never call the dump command without the -command flag, since the 3692 # output could involve Tcl quoting and would be a pain to parse 3693 # right. Instead just set the command to build a list of triples 3694 # as if we had done the parsing. 3695 result = [] 3696 def append_triple(key, value, index, result=result): 3697 result.append((key, value, index)) 3698 command = append_triple 3699 try: 3700 if not isinstance(command, str): 3701 func_name = command = self._register(command) 3702 args += ["-command", command] 3703 for key in kw: 3704 if kw[key]: args.append("-" + key) 3705 args.append(index1) 3706 if index2: 3707 args.append(index2) 3708 self.tk.call(self._w, "dump", *args) 3709 return result 3710 finally: 3711 if func_name: 3712 self.deletecommand(func_name) 3713 3714 ## new in tk8.4 3715 def edit(self, *args): 3716 """Internal method 3717 3718 This method controls the undo mechanism and 3719 the modified flag. The exact behavior of the 3720 command depends on the option argument that 3721 follows the edit argument. The following forms 3722 of the command are currently supported: 3723 3724 edit_modified, edit_redo, edit_reset, edit_separator 3725 and edit_undo 3726 3727 """ 3728 return self.tk.call(self._w, 'edit', *args) 3729 3730 def edit_modified(self, arg=None): 3731 """Get or Set the modified flag 3732 3733 If arg is not specified, returns the modified 3734 flag of the widget. The insert, delete, edit undo and 3735 edit redo commands or the user can set or clear the 3736 modified flag. If boolean is specified, sets the 3737 modified flag of the widget to arg. 3738 """ 3739 return self.edit("modified", arg) 3740 3741 def edit_redo(self): 3742 """Redo the last undone edit 3743 3744 When the undo option is true, reapplies the last 3745 undone edits provided no other edits were done since 3746 then. Generates an error when the redo stack is empty. 3747 Does nothing when the undo option is false. 3748 """ 3749 return self.edit("redo") 3750 3751 def edit_reset(self): 3752 """Clears the undo and redo stacks 3753 """ 3754 return self.edit("reset") 3755 3756 def edit_separator(self): 3757 """Inserts a separator (boundary) on the undo stack. 3758 3759 Does nothing when the undo option is false 3760 """ 3761 return self.edit("separator") 3762 3763 def edit_undo(self): 3764 """Undoes the last edit action 3765 3766 If the undo option is true. An edit action is defined 3767 as all the insert and delete commands that are recorded 3768 on the undo stack in between two separators. Generates 3769 an error when the undo stack is empty. Does nothing 3770 when the undo option is false 3771 """ 3772 return self.edit("undo") 3773 3774 def get(self, index1, index2=None): 3775 """Return the text from INDEX1 to INDEX2 (not included).""" 3776 return self.tk.call(self._w, 'get', index1, index2) 3777 # (Image commands are new in 8.0) 3778 3779 def image_cget(self, index, option): 3780 """Return the value of OPTION of an embedded image at INDEX.""" 3781 if option[:1] != "-": 3782 option = "-" + option 3783 if option[-1:] == "_": 3784 option = option[:-1] 3785 return self.tk.call(self._w, "image", "cget", index, option) 3786 3787 def image_configure(self, index, cnf=None, **kw): 3788 """Configure an embedded image at INDEX.""" 3789 return self._configure(('image', 'configure', index), cnf, kw) 3790 3791 def image_create(self, index, cnf={}, **kw): 3792 """Create an embedded image at INDEX.""" 3793 return self.tk.call( 3794 self._w, "image", "create", index, 3795 *self._options(cnf, kw)) 3796 3797 def image_names(self): 3798 """Return all names of embedded images in this widget.""" 3799 return self.tk.call(self._w, "image", "names") 3800 3801 def index(self, index): 3802 """Return the index in the form line.char for INDEX.""" 3803 return str(self.tk.call(self._w, 'index', index)) 3804 3805 def insert(self, index, chars, *args): 3806 """Insert CHARS before the characters at INDEX. An additional 3807 tag can be given in ARGS. Additional CHARS and tags can follow in ARGS.""" 3808 self.tk.call((self._w, 'insert', index, chars) + args) 3809 3810 def mark_gravity(self, markName, direction=None): 3811 """Change the gravity of a mark MARKNAME to DIRECTION (LEFT or RIGHT). 3812 Return the current value if None is given for DIRECTION.""" 3813 return self.tk.call( 3814 (self._w, 'mark', 'gravity', markName, direction)) 3815 3816 def mark_names(self): 3817 """Return all mark names.""" 3818 return self.tk.splitlist(self.tk.call( 3819 self._w, 'mark', 'names')) 3820 3821 def mark_set(self, markName, index): 3822 """Set mark MARKNAME before the character at INDEX.""" 3823 self.tk.call(self._w, 'mark', 'set', markName, index) 3824 3825 def mark_unset(self, *markNames): 3826 """Delete all marks in MARKNAMES.""" 3827 self.tk.call((self._w, 'mark', 'unset') + markNames) 3828 3829 def mark_next(self, index): 3830 """Return the name of the next mark after INDEX.""" 3831 return self.tk.call(self._w, 'mark', 'next', index) or None 3832 3833 def mark_previous(self, index): 3834 """Return the name of the previous mark before INDEX.""" 3835 return self.tk.call(self._w, 'mark', 'previous', index) or None 3836 3837 def peer_create(self, newPathName, cnf={}, **kw): # new in Tk 8.5 3838 """Creates a peer text widget with the given newPathName, and any 3839 optional standard configuration options. By default the peer will 3840 have the same start and end line as the parent widget, but 3841 these can be overridden with the standard configuration options.""" 3842 self.tk.call(self._w, 'peer', 'create', newPathName, 3843 *self._options(cnf, kw)) 3844 3845 def peer_names(self): # new in Tk 8.5 3846 """Returns a list of peers of this widget (this does not include 3847 the widget itself).""" 3848 return self.tk.splitlist(self.tk.call(self._w, 'peer', 'names')) 3849 3850 def replace(self, index1, index2, chars, *args): # new in Tk 8.5 3851 """Replaces the range of characters between index1 and index2 with 3852 the given characters and tags specified by args. 3853 3854 See the method insert for some more information about args, and the 3855 method delete for information about the indices.""" 3856 self.tk.call(self._w, 'replace', index1, index2, chars, *args) 3857 3858 def scan_mark(self, x, y): 3859 """Remember the current X, Y coordinates.""" 3860 self.tk.call(self._w, 'scan', 'mark', x, y) 3861 3862 def scan_dragto(self, x, y): 3863 """Adjust the view of the text to 10 times the 3864 difference between X and Y and the coordinates given in 3865 scan_mark.""" 3866 self.tk.call(self._w, 'scan', 'dragto', x, y) 3867 3868 def search(self, pattern, index, stopindex=None, 3869 forwards=None, backwards=None, exact=None, 3870 regexp=None, nocase=None, count=None, elide=None): 3871 """Search PATTERN beginning from INDEX until STOPINDEX. 3872 Return the index of the first character of a match or an 3873 empty string.""" 3874 args = [self._w, 'search'] 3875 if forwards: args.append('-forwards') 3876 if backwards: args.append('-backwards') 3877 if exact: args.append('-exact') 3878 if regexp: args.append('-regexp') 3879 if nocase: args.append('-nocase') 3880 if elide: args.append('-elide') 3881 if count: args.append('-count'); args.append(count) 3882 if pattern and pattern[0] == '-': args.append('--') 3883 args.append(pattern) 3884 args.append(index) 3885 if stopindex: args.append(stopindex) 3886 return str(self.tk.call(tuple(args))) 3887 3888 def see(self, index): 3889 """Scroll such that the character at INDEX is visible.""" 3890 self.tk.call(self._w, 'see', index) 3891 3892 def tag_add(self, tagName, index1, *args): 3893 """Add tag TAGNAME to all characters between INDEX1 and index2 in ARGS. 3894 Additional pairs of indices may follow in ARGS.""" 3895 self.tk.call( 3896 (self._w, 'tag', 'add', tagName, index1) + args) 3897 3898 def tag_unbind(self, tagName, sequence, funcid=None): 3899 """Unbind for all characters with TAGNAME for event SEQUENCE the 3900 function identified with FUNCID.""" 3901 self.tk.call(self._w, 'tag', 'bind', tagName, sequence, '') 3902 if funcid: 3903 self.deletecommand(funcid) 3904 3905 def tag_bind(self, tagName, sequence, func, add=None): 3906 """Bind to all characters with TAGNAME at event SEQUENCE a call to function FUNC. 3907 3908 An additional boolean parameter ADD specifies whether FUNC will be 3909 called additionally to the other bound function or whether it will 3910 replace the previous function. See bind for the return value.""" 3911 return self._bind((self._w, 'tag', 'bind', tagName), 3912 sequence, func, add) 3913 3914 def tag_cget(self, tagName, option): 3915 """Return the value of OPTION for tag TAGNAME.""" 3916 if option[:1] != '-': 3917 option = '-' + option 3918 if option[-1:] == '_': 3919 option = option[:-1] 3920 return self.tk.call(self._w, 'tag', 'cget', tagName, option) 3921 3922 def tag_configure(self, tagName, cnf=None, **kw): 3923 """Configure a tag TAGNAME.""" 3924 return self._configure(('tag', 'configure', tagName), cnf, kw) 3925 3926 tag_config = tag_configure 3927 3928 def tag_delete(self, *tagNames): 3929 """Delete all tags in TAGNAMES.""" 3930 self.tk.call((self._w, 'tag', 'delete') + tagNames) 3931 3932 def tag_lower(self, tagName, belowThis=None): 3933 """Change the priority of tag TAGNAME such that it is lower 3934 than the priority of BELOWTHIS.""" 3935 self.tk.call(self._w, 'tag', 'lower', tagName, belowThis) 3936 3937 def tag_names(self, index=None): 3938 """Return a list of all tag names.""" 3939 return self.tk.splitlist( 3940 self.tk.call(self._w, 'tag', 'names', index)) 3941 3942 def tag_nextrange(self, tagName, index1, index2=None): 3943 """Return a list of start and end index for the first sequence of 3944 characters between INDEX1 and INDEX2 which all have tag TAGNAME. 3945 The text is searched forward from INDEX1.""" 3946 return self.tk.splitlist(self.tk.call( 3947 self._w, 'tag', 'nextrange', tagName, index1, index2)) 3948 3949 def tag_prevrange(self, tagName, index1, index2=None): 3950 """Return a list of start and end index for the first sequence of 3951 characters between INDEX1 and INDEX2 which all have tag TAGNAME. 3952 The text is searched backwards from INDEX1.""" 3953 return self.tk.splitlist(self.tk.call( 3954 self._w, 'tag', 'prevrange', tagName, index1, index2)) 3955 3956 def tag_raise(self, tagName, aboveThis=None): 3957 """Change the priority of tag TAGNAME such that it is higher 3958 than the priority of ABOVETHIS.""" 3959 self.tk.call( 3960 self._w, 'tag', 'raise', tagName, aboveThis) 3961 3962 def tag_ranges(self, tagName): 3963 """Return a list of ranges of text which have tag TAGNAME.""" 3964 return self.tk.splitlist(self.tk.call( 3965 self._w, 'tag', 'ranges', tagName)) 3966 3967 def tag_remove(self, tagName, index1, index2=None): 3968 """Remove tag TAGNAME from all characters between INDEX1 and INDEX2.""" 3969 self.tk.call( 3970 self._w, 'tag', 'remove', tagName, index1, index2) 3971 3972 def window_cget(self, index, option): 3973 """Return the value of OPTION of an embedded window at INDEX.""" 3974 if option[:1] != '-': 3975 option = '-' + option 3976 if option[-1:] == '_': 3977 option = option[:-1] 3978 return self.tk.call(self._w, 'window', 'cget', index, option) 3979 3980 def window_configure(self, index, cnf=None, **kw): 3981 """Configure an embedded window at INDEX.""" 3982 return self._configure(('window', 'configure', index), cnf, kw) 3983 3984 window_config = window_configure 3985 3986 def window_create(self, index, cnf={}, **kw): 3987 """Create a window at INDEX.""" 3988 self.tk.call( 3989 (self._w, 'window', 'create', index) 3990 + self._options(cnf, kw)) 3991 3992 def window_names(self): 3993 """Return all names of embedded windows in this widget.""" 3994 return self.tk.splitlist( 3995 self.tk.call(self._w, 'window', 'names')) 3996 3997 def yview_pickplace(self, *what): 3998 """Obsolete function, use see.""" 3999 self.tk.call((self._w, 'yview', '-pickplace') + what) 4000 4001 4002class _setit: 4003 """Internal class. It wraps the command in the widget OptionMenu.""" 4004 4005 def __init__(self, var, value, callback=None): 4006 self.__value = value 4007 self.__var = var 4008 self.__callback = callback 4009 4010 def __call__(self, *args): 4011 self.__var.set(self.__value) 4012 if self.__callback is not None: 4013 self.__callback(self.__value, *args) 4014 4015 4016class OptionMenu(Menubutton): 4017 """OptionMenu which allows the user to select a value from a menu.""" 4018 4019 def __init__(self, master, variable, value, *values, **kwargs): 4020 """Construct an optionmenu widget with the parent MASTER, with 4021 the resource textvariable set to VARIABLE, the initially selected 4022 value VALUE, the other menu values VALUES and an additional 4023 keyword argument command.""" 4024 kw = {"borderwidth": 2, "textvariable": variable, 4025 "indicatoron": 1, "relief": RAISED, "anchor": "c", 4026 "highlightthickness": 2} 4027 Widget.__init__(self, master, "menubutton", kw) 4028 self.widgetName = 'tk_optionMenu' 4029 menu = self.__menu = Menu(self, name="menu", tearoff=0) 4030 self.menuname = menu._w 4031 # 'command' is the only supported keyword 4032 callback = kwargs.get('command') 4033 if 'command' in kwargs: 4034 del kwargs['command'] 4035 if kwargs: 4036 raise TclError('unknown option -'+next(iter(kwargs))) 4037 menu.add_command(label=value, 4038 command=_setit(variable, value, callback)) 4039 for v in values: 4040 menu.add_command(label=v, 4041 command=_setit(variable, v, callback)) 4042 self["menu"] = menu 4043 4044 def __getitem__(self, name): 4045 if name == 'menu': 4046 return self.__menu 4047 return Widget.__getitem__(self, name) 4048 4049 def destroy(self): 4050 """Destroy this widget and the associated menu.""" 4051 Menubutton.destroy(self) 4052 self.__menu = None 4053 4054 4055class Image: 4056 """Base class for images.""" 4057 _last_id = 0 4058 4059 def __init__(self, imgtype, name=None, cnf={}, master=None, **kw): 4060 self.name = None 4061 if master is None: 4062 master = _get_default_root('create image') 4063 self.tk = getattr(master, 'tk', master) 4064 if not name: 4065 Image._last_id += 1 4066 name = "pyimage%r" % (Image._last_id,) # tk itself would use image<x> 4067 if kw and cnf: cnf = _cnfmerge((cnf, kw)) 4068 elif kw: cnf = kw 4069 options = () 4070 for k, v in cnf.items(): 4071 if callable(v): 4072 v = self._register(v) 4073 options = options + ('-'+k, v) 4074 self.tk.call(('image', 'create', imgtype, name,) + options) 4075 self.name = name 4076 4077 def __str__(self): return self.name 4078 4079 def __del__(self): 4080 if self.name: 4081 try: 4082 self.tk.call('image', 'delete', self.name) 4083 except TclError: 4084 # May happen if the root was destroyed 4085 pass 4086 4087 def __setitem__(self, key, value): 4088 self.tk.call(self.name, 'configure', '-'+key, value) 4089 4090 def __getitem__(self, key): 4091 return self.tk.call(self.name, 'configure', '-'+key) 4092 4093 def configure(self, **kw): 4094 """Configure the image.""" 4095 res = () 4096 for k, v in _cnfmerge(kw).items(): 4097 if v is not None: 4098 if k[-1] == '_': k = k[:-1] 4099 if callable(v): 4100 v = self._register(v) 4101 res = res + ('-'+k, v) 4102 self.tk.call((self.name, 'config') + res) 4103 4104 config = configure 4105 4106 def height(self): 4107 """Return the height of the image.""" 4108 return self.tk.getint( 4109 self.tk.call('image', 'height', self.name)) 4110 4111 def type(self): 4112 """Return the type of the image, e.g. "photo" or "bitmap".""" 4113 return self.tk.call('image', 'type', self.name) 4114 4115 def width(self): 4116 """Return the width of the image.""" 4117 return self.tk.getint( 4118 self.tk.call('image', 'width', self.name)) 4119 4120 4121class PhotoImage(Image): 4122 """Widget which can display images in PGM, PPM, GIF, PNG format.""" 4123 4124 def __init__(self, name=None, cnf={}, master=None, **kw): 4125 """Create an image with NAME. 4126 4127 Valid resource names: data, format, file, gamma, height, palette, 4128 width.""" 4129 Image.__init__(self, 'photo', name, cnf, master, **kw) 4130 4131 def blank(self): 4132 """Display a transparent image.""" 4133 self.tk.call(self.name, 'blank') 4134 4135 def cget(self, option): 4136 """Return the value of OPTION.""" 4137 return self.tk.call(self.name, 'cget', '-' + option) 4138 # XXX config 4139 4140 def __getitem__(self, key): 4141 return self.tk.call(self.name, 'cget', '-' + key) 4142 # XXX copy -from, -to, ...? 4143 4144 def copy(self): 4145 """Return a new PhotoImage with the same image as this widget.""" 4146 destImage = PhotoImage(master=self.tk) 4147 self.tk.call(destImage, 'copy', self.name) 4148 return destImage 4149 4150 def zoom(self, x, y=''): 4151 """Return a new PhotoImage with the same image as this widget 4152 but zoom it with a factor of x in the X direction and y in the Y 4153 direction. If y is not given, the default value is the same as x. 4154 """ 4155 destImage = PhotoImage(master=self.tk) 4156 if y=='': y=x 4157 self.tk.call(destImage, 'copy', self.name, '-zoom',x,y) 4158 return destImage 4159 4160 def subsample(self, x, y=''): 4161 """Return a new PhotoImage based on the same image as this widget 4162 but use only every Xth or Yth pixel. If y is not given, the 4163 default value is the same as x. 4164 """ 4165 destImage = PhotoImage(master=self.tk) 4166 if y=='': y=x 4167 self.tk.call(destImage, 'copy', self.name, '-subsample',x,y) 4168 return destImage 4169 4170 def get(self, x, y): 4171 """Return the color (red, green, blue) of the pixel at X,Y.""" 4172 return self.tk.call(self.name, 'get', x, y) 4173 4174 def put(self, data, to=None): 4175 """Put row formatted colors to image starting from 4176 position TO, e.g. image.put("{red green} {blue yellow}", to=(4,6))""" 4177 args = (self.name, 'put', data) 4178 if to: 4179 if to[0] == '-to': 4180 to = to[1:] 4181 args = args + ('-to',) + tuple(to) 4182 self.tk.call(args) 4183 # XXX read 4184 4185 def write(self, filename, format=None, from_coords=None): 4186 """Write image to file FILENAME in FORMAT starting from 4187 position FROM_COORDS.""" 4188 args = (self.name, 'write', filename) 4189 if format: 4190 args = args + ('-format', format) 4191 if from_coords: 4192 args = args + ('-from',) + tuple(from_coords) 4193 self.tk.call(args) 4194 4195 def transparency_get(self, x, y): 4196 """Return True if the pixel at x,y is transparent.""" 4197 return self.tk.getboolean(self.tk.call( 4198 self.name, 'transparency', 'get', x, y)) 4199 4200 def transparency_set(self, x, y, boolean): 4201 """Set the transparency of the pixel at x,y.""" 4202 self.tk.call(self.name, 'transparency', 'set', x, y, boolean) 4203 4204 4205class BitmapImage(Image): 4206 """Widget which can display images in XBM format.""" 4207 4208 def __init__(self, name=None, cnf={}, master=None, **kw): 4209 """Create a bitmap with NAME. 4210 4211 Valid resource names: background, data, file, foreground, maskdata, maskfile.""" 4212 Image.__init__(self, 'bitmap', name, cnf, master, **kw) 4213 4214 4215def image_names(): 4216 tk = _get_default_root('use image_names()').tk 4217 return tk.splitlist(tk.call('image', 'names')) 4218 4219 4220def image_types(): 4221 tk = _get_default_root('use image_types()').tk 4222 return tk.splitlist(tk.call('image', 'types')) 4223 4224 4225class Spinbox(Widget, XView): 4226 """spinbox widget.""" 4227 4228 def __init__(self, master=None, cnf={}, **kw): 4229 """Construct a spinbox widget with the parent MASTER. 4230 4231 STANDARD OPTIONS 4232 4233 activebackground, background, borderwidth, 4234 cursor, exportselection, font, foreground, 4235 highlightbackground, highlightcolor, 4236 highlightthickness, insertbackground, 4237 insertborderwidth, insertofftime, 4238 insertontime, insertwidth, justify, relief, 4239 repeatdelay, repeatinterval, 4240 selectbackground, selectborderwidth 4241 selectforeground, takefocus, textvariable 4242 xscrollcommand. 4243 4244 WIDGET-SPECIFIC OPTIONS 4245 4246 buttonbackground, buttoncursor, 4247 buttondownrelief, buttonuprelief, 4248 command, disabledbackground, 4249 disabledforeground, format, from, 4250 invalidcommand, increment, 4251 readonlybackground, state, to, 4252 validate, validatecommand values, 4253 width, wrap, 4254 """ 4255 Widget.__init__(self, master, 'spinbox', cnf, kw) 4256 4257 def bbox(self, index): 4258 """Return a tuple of X1,Y1,X2,Y2 coordinates for a 4259 rectangle which encloses the character given by index. 4260 4261 The first two elements of the list give the x and y 4262 coordinates of the upper-left corner of the screen 4263 area covered by the character (in pixels relative 4264 to the widget) and the last two elements give the 4265 width and height of the character, in pixels. The 4266 bounding box may refer to a region outside the 4267 visible area of the window. 4268 """ 4269 return self._getints(self.tk.call(self._w, 'bbox', index)) or None 4270 4271 def delete(self, first, last=None): 4272 """Delete one or more elements of the spinbox. 4273 4274 First is the index of the first character to delete, 4275 and last is the index of the character just after 4276 the last one to delete. If last isn't specified it 4277 defaults to first+1, i.e. a single character is 4278 deleted. This command returns an empty string. 4279 """ 4280 return self.tk.call(self._w, 'delete', first, last) 4281 4282 def get(self): 4283 """Returns the spinbox's string""" 4284 return self.tk.call(self._w, 'get') 4285 4286 def icursor(self, index): 4287 """Alter the position of the insertion cursor. 4288 4289 The insertion cursor will be displayed just before 4290 the character given by index. Returns an empty string 4291 """ 4292 return self.tk.call(self._w, 'icursor', index) 4293 4294 def identify(self, x, y): 4295 """Returns the name of the widget at position x, y 4296 4297 Return value is one of: none, buttondown, buttonup, entry 4298 """ 4299 return self.tk.call(self._w, 'identify', x, y) 4300 4301 def index(self, index): 4302 """Returns the numerical index corresponding to index 4303 """ 4304 return self.tk.call(self._w, 'index', index) 4305 4306 def insert(self, index, s): 4307 """Insert string s at index 4308 4309 Returns an empty string. 4310 """ 4311 return self.tk.call(self._w, 'insert', index, s) 4312 4313 def invoke(self, element): 4314 """Causes the specified element to be invoked 4315 4316 The element could be buttondown or buttonup 4317 triggering the action associated with it. 4318 """ 4319 return self.tk.call(self._w, 'invoke', element) 4320 4321 def scan(self, *args): 4322 """Internal function.""" 4323 return self._getints( 4324 self.tk.call((self._w, 'scan') + args)) or () 4325 4326 def scan_mark(self, x): 4327 """Records x and the current view in the spinbox window; 4328 4329 used in conjunction with later scan dragto commands. 4330 Typically this command is associated with a mouse button 4331 press in the widget. It returns an empty string. 4332 """ 4333 return self.scan("mark", x) 4334 4335 def scan_dragto(self, x): 4336 """Compute the difference between the given x argument 4337 and the x argument to the last scan mark command 4338 4339 It then adjusts the view left or right by 10 times the 4340 difference in x-coordinates. This command is typically 4341 associated with mouse motion events in the widget, to 4342 produce the effect of dragging the spinbox at high speed 4343 through the window. The return value is an empty string. 4344 """ 4345 return self.scan("dragto", x) 4346 4347 def selection(self, *args): 4348 """Internal function.""" 4349 return self._getints( 4350 self.tk.call((self._w, 'selection') + args)) or () 4351 4352 def selection_adjust(self, index): 4353 """Locate the end of the selection nearest to the character 4354 given by index, 4355 4356 Then adjust that end of the selection to be at index 4357 (i.e including but not going beyond index). The other 4358 end of the selection is made the anchor point for future 4359 select to commands. If the selection isn't currently in 4360 the spinbox, then a new selection is created to include 4361 the characters between index and the most recent selection 4362 anchor point, inclusive. 4363 """ 4364 return self.selection("adjust", index) 4365 4366 def selection_clear(self): 4367 """Clear the selection 4368 4369 If the selection isn't in this widget then the 4370 command has no effect. 4371 """ 4372 return self.selection("clear") 4373 4374 def selection_element(self, element=None): 4375 """Sets or gets the currently selected element. 4376 4377 If a spinbutton element is specified, it will be 4378 displayed depressed. 4379 """ 4380 return self.tk.call(self._w, 'selection', 'element', element) 4381 4382 def selection_from(self, index): 4383 """Set the fixed end of a selection to INDEX.""" 4384 self.selection('from', index) 4385 4386 def selection_present(self): 4387 """Return True if there are characters selected in the spinbox, False 4388 otherwise.""" 4389 return self.tk.getboolean( 4390 self.tk.call(self._w, 'selection', 'present')) 4391 4392 def selection_range(self, start, end): 4393 """Set the selection from START to END (not included).""" 4394 self.selection('range', start, end) 4395 4396 def selection_to(self, index): 4397 """Set the variable end of a selection to INDEX.""" 4398 self.selection('to', index) 4399 4400########################################################################### 4401 4402 4403class LabelFrame(Widget): 4404 """labelframe widget.""" 4405 4406 def __init__(self, master=None, cnf={}, **kw): 4407 """Construct a labelframe widget with the parent MASTER. 4408 4409 STANDARD OPTIONS 4410 4411 borderwidth, cursor, font, foreground, 4412 highlightbackground, highlightcolor, 4413 highlightthickness, padx, pady, relief, 4414 takefocus, text 4415 4416 WIDGET-SPECIFIC OPTIONS 4417 4418 background, class, colormap, container, 4419 height, labelanchor, labelwidget, 4420 visual, width 4421 """ 4422 Widget.__init__(self, master, 'labelframe', cnf, kw) 4423 4424######################################################################## 4425 4426 4427class PanedWindow(Widget): 4428 """panedwindow widget.""" 4429 4430 def __init__(self, master=None, cnf={}, **kw): 4431 """Construct a panedwindow widget with the parent MASTER. 4432 4433 STANDARD OPTIONS 4434 4435 background, borderwidth, cursor, height, 4436 orient, relief, width 4437 4438 WIDGET-SPECIFIC OPTIONS 4439 4440 handlepad, handlesize, opaqueresize, 4441 sashcursor, sashpad, sashrelief, 4442 sashwidth, showhandle, 4443 """ 4444 Widget.__init__(self, master, 'panedwindow', cnf, kw) 4445 4446 def add(self, child, **kw): 4447 """Add a child widget to the panedwindow in a new pane. 4448 4449 The child argument is the name of the child widget 4450 followed by pairs of arguments that specify how to 4451 manage the windows. The possible options and values 4452 are the ones accepted by the paneconfigure method. 4453 """ 4454 self.tk.call((self._w, 'add', child) + self._options(kw)) 4455 4456 def remove(self, child): 4457 """Remove the pane containing child from the panedwindow 4458 4459 All geometry management options for child will be forgotten. 4460 """ 4461 self.tk.call(self._w, 'forget', child) 4462 4463 forget = remove 4464 4465 def identify(self, x, y): 4466 """Identify the panedwindow component at point x, y 4467 4468 If the point is over a sash or a sash handle, the result 4469 is a two element list containing the index of the sash or 4470 handle, and a word indicating whether it is over a sash 4471 or a handle, such as {0 sash} or {2 handle}. If the point 4472 is over any other part of the panedwindow, the result is 4473 an empty list. 4474 """ 4475 return self.tk.call(self._w, 'identify', x, y) 4476 4477 def proxy(self, *args): 4478 """Internal function.""" 4479 return self._getints( 4480 self.tk.call((self._w, 'proxy') + args)) or () 4481 4482 def proxy_coord(self): 4483 """Return the x and y pair of the most recent proxy location 4484 """ 4485 return self.proxy("coord") 4486 4487 def proxy_forget(self): 4488 """Remove the proxy from the display. 4489 """ 4490 return self.proxy("forget") 4491 4492 def proxy_place(self, x, y): 4493 """Place the proxy at the given x and y coordinates. 4494 """ 4495 return self.proxy("place", x, y) 4496 4497 def sash(self, *args): 4498 """Internal function.""" 4499 return self._getints( 4500 self.tk.call((self._w, 'sash') + args)) or () 4501 4502 def sash_coord(self, index): 4503 """Return the current x and y pair for the sash given by index. 4504 4505 Index must be an integer between 0 and 1 less than the 4506 number of panes in the panedwindow. The coordinates given are 4507 those of the top left corner of the region containing the sash. 4508 pathName sash dragto index x y This command computes the 4509 difference between the given coordinates and the coordinates 4510 given to the last sash coord command for the given sash. It then 4511 moves that sash the computed difference. The return value is the 4512 empty string. 4513 """ 4514 return self.sash("coord", index) 4515 4516 def sash_mark(self, index): 4517 """Records x and y for the sash given by index; 4518 4519 Used in conjunction with later dragto commands to move the sash. 4520 """ 4521 return self.sash("mark", index) 4522 4523 def sash_place(self, index, x, y): 4524 """Place the sash given by index at the given coordinates 4525 """ 4526 return self.sash("place", index, x, y) 4527 4528 def panecget(self, child, option): 4529 """Query a management option for window. 4530 4531 Option may be any value allowed by the paneconfigure subcommand 4532 """ 4533 return self.tk.call( 4534 (self._w, 'panecget') + (child, '-'+option)) 4535 4536 def paneconfigure(self, tagOrId, cnf=None, **kw): 4537 """Query or modify the management options for window. 4538 4539 If no option is specified, returns a list describing all 4540 of the available options for pathName. If option is 4541 specified with no value, then the command returns a list 4542 describing the one named option (this list will be identical 4543 to the corresponding sublist of the value returned if no 4544 option is specified). If one or more option-value pairs are 4545 specified, then the command modifies the given widget 4546 option(s) to have the given value(s); in this case the 4547 command returns an empty string. The following options 4548 are supported: 4549 4550 after window 4551 Insert the window after the window specified. window 4552 should be the name of a window already managed by pathName. 4553 before window 4554 Insert the window before the window specified. window 4555 should be the name of a window already managed by pathName. 4556 height size 4557 Specify a height for the window. The height will be the 4558 outer dimension of the window including its border, if 4559 any. If size is an empty string, or if -height is not 4560 specified, then the height requested internally by the 4561 window will be used initially; the height may later be 4562 adjusted by the movement of sashes in the panedwindow. 4563 Size may be any value accepted by Tk_GetPixels. 4564 minsize n 4565 Specifies that the size of the window cannot be made 4566 less than n. This constraint only affects the size of 4567 the widget in the paned dimension -- the x dimension 4568 for horizontal panedwindows, the y dimension for 4569 vertical panedwindows. May be any value accepted by 4570 Tk_GetPixels. 4571 padx n 4572 Specifies a non-negative value indicating how much 4573 extra space to leave on each side of the window in 4574 the X-direction. The value may have any of the forms 4575 accepted by Tk_GetPixels. 4576 pady n 4577 Specifies a non-negative value indicating how much 4578 extra space to leave on each side of the window in 4579 the Y-direction. The value may have any of the forms 4580 accepted by Tk_GetPixels. 4581 sticky style 4582 If a window's pane is larger than the requested 4583 dimensions of the window, this option may be used 4584 to position (or stretch) the window within its pane. 4585 Style is a string that contains zero or more of the 4586 characters n, s, e or w. The string can optionally 4587 contains spaces or commas, but they are ignored. Each 4588 letter refers to a side (north, south, east, or west) 4589 that the window will "stick" to. If both n and s 4590 (or e and w) are specified, the window will be 4591 stretched to fill the entire height (or width) of 4592 its cavity. 4593 width size 4594 Specify a width for the window. The width will be 4595 the outer dimension of the window including its 4596 border, if any. If size is an empty string, or 4597 if -width is not specified, then the width requested 4598 internally by the window will be used initially; the 4599 width may later be adjusted by the movement of sashes 4600 in the panedwindow. Size may be any value accepted by 4601 Tk_GetPixels. 4602 4603 """ 4604 if cnf is None and not kw: 4605 return self._getconfigure(self._w, 'paneconfigure', tagOrId) 4606 if isinstance(cnf, str) and not kw: 4607 return self._getconfigure1( 4608 self._w, 'paneconfigure', tagOrId, '-'+cnf) 4609 self.tk.call((self._w, 'paneconfigure', tagOrId) + 4610 self._options(cnf, kw)) 4611 4612 paneconfig = paneconfigure 4613 4614 def panes(self): 4615 """Returns an ordered list of the child panes.""" 4616 return self.tk.splitlist(self.tk.call(self._w, 'panes')) 4617 4618# Test: 4619 4620 4621def _test(): 4622 root = Tk() 4623 text = "This is Tcl/Tk version %s" % TclVersion 4624 text += "\nThis should be a cedilla: \xe7" 4625 label = Label(root, text=text) 4626 label.pack() 4627 test = Button(root, text="Click me!", 4628 command=lambda root=root: root.test.configure( 4629 text="[%s]" % root.test['text'])) 4630 test.pack() 4631 root.test = test 4632 quit = Button(root, text="QUIT", command=root.destroy) 4633 quit.pack() 4634 # The following three commands are needed so the window pops 4635 # up on top on Windows... 4636 root.iconify() 4637 root.update() 4638 root.deiconify() 4639 root.mainloop() 4640 4641 4642__all__ = [name for name, obj in globals().items() 4643 if not name.startswith('_') and not isinstance(obj, types.ModuleType) 4644 and name not in {'wantobjects'}] 4645 4646if __name__ == '__main__': 4647 _test() 4648