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