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