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