summaryrefslogtreecommitdiff
path: root/Lib/tkinter/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/tkinter/__init__.py')
-rw-r--r--Lib/tkinter/__init__.py253
1 files changed, 194 insertions, 59 deletions
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 1286779b99..b9e5d2ef2e 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -30,17 +30,19 @@ button.pack(side=BOTTOM)
tk.mainloop()
"""
-__version__ = "$Revision$"
-
import sys
if sys.platform == "win32":
# Attempt to configure Tcl/Tk without requiring PATH
from tkinter import _fix
+
+import warnings
+
import _tkinter # If this fails your Python may not be configured for Tk
TclError = _tkinter.TclError
from tkinter.constants import *
import re
+
wantobjects = 1
TkVersion = float(_tkinter.TK_VERSION)
@@ -190,6 +192,7 @@ class Variable:
Subclasses StringVar, IntVar, DoubleVar, BooleanVar are specializations
that constrain the type of the value returned from get()."""
_default = ""
+ _tk = None
def __init__(self, master=None, value=None, name=None):
"""Construct a variable
@@ -200,6 +203,11 @@ class Variable:
If NAME matches an existing variable and VALUE is omitted
then the existing value is retained.
"""
+ # check for type of NAME parameter to override weird error message
+ # raised from Modules/_tkinter.c:SetVar like:
+ # TypeError: setvar() takes exactly 3 arguments (2 given)
+ if name is not None and not isinstance(name, str):
+ raise TypeError("name must be a string")
global _varnum
if not master:
master = _default_root
@@ -211,18 +219,21 @@ class Variable:
self._name = 'PY_VAR' + repr(_varnum)
_varnum += 1
if value is not None:
- self.set(value)
- elif not self._tk.call("info", "exists", self._name):
- self.set(self._default)
+ self.initialize(value)
+ elif not self._tk.getboolean(self._tk.call("info", "exists", self._name)):
+ self.initialize(self._default)
def __del__(self):
"""Unset the variable in Tcl."""
- self._tk.globalunsetvar(self._name)
+ if (self._tk is not None and
+ self._tk.getboolean(self._tk.call("info", "exists", self._name))):
+ self._tk.globalunsetvar(self._name)
def __str__(self):
"""Return the name of the variable in Tcl."""
return self._name
def set(self, value):
"""Set the variable to VALUE."""
return self._tk.globalsetvar(self._name, value)
+ initialize = set
def get(self):
"""Return value of variable."""
return self._tk.globalgetvar(self._name)
@@ -297,12 +308,6 @@ class IntVar(Variable):
"""
Variable.__init__(self, master, value, name)
- def set(self, value):
- """Set the variable to value, converting booleans to integers."""
- if isinstance(value, bool):
- value = int(value)
- return Variable.set(self, value)
-
def get(self):
"""Return the value of the variable as an integer."""
return getint(self._tk.globalgetvar(self._name))
@@ -343,7 +348,10 @@ class BooleanVar(Variable):
def get(self):
"""Return the value of the variable as a bool."""
- return self._tk.getboolean(self._tk.globalgetvar(self._name))
+ try:
+ return self._tk.getboolean(self._tk.globalgetvar(self._name))
+ except TclError:
+ raise ValueError("invalid literal for getboolean()")
def mainloop(n=0):
"""Run the main loop of Tcl."""
@@ -355,7 +363,10 @@ getdouble = float
def getboolean(s):
"""Convert true and false to integer values 1 and 0."""
- return _default_root.tk.getboolean(s)
+ try:
+ return _default_root.tk.getboolean(s)
+ except TclError:
+ raise ValueError("invalid literal for getboolean()")
# Methods defined on both toplevel and interior widgets
class Misc:
@@ -445,7 +456,10 @@ class Misc:
getdouble = float
def getboolean(self, s):
"""Return a boolean value for Tcl boolean values true and false given as parameter."""
- return self.tk.getboolean(s)
+ try:
+ return self.tk.getboolean(s)
+ except TclError:
+ raise ValueError("invalid literal for getboolean()")
def focus_set(self):
"""Direct input focus to this widget.
@@ -1218,10 +1232,22 @@ class Misc:
return (e,)
def _report_exception(self):
"""Internal function."""
- import sys
exc, val, tb = sys.exc_info()
root = self._root()
root.report_callback_exception(exc, val, tb)
+
+ def _getconfigure(self, *args):
+ """Call Tcl configure command and return the result as a dict."""
+ cnf = {}
+ for x in self.tk.splitlist(self.tk.call(*args)):
+ x = self.tk.splitlist(x)
+ cnf[x[0][1:]] = (x[0][1:],) + x[1:]
+ return cnf
+
+ def _getconfigure1(self, *args):
+ x = self.tk.splitlist(self.tk.call(*args))
+ return (x[0][1:],) + x[1:]
+
def _configure(self, cmd, cnf, kw):
"""Internal function."""
if kw:
@@ -1229,15 +1255,9 @@ class Misc:
elif cnf:
cnf = _cnfmerge(cnf)
if cnf is None:
- cnf = {}
- for x in self.tk.split(
- self.tk.call(_flatten((self._w, cmd)))):
- cnf[x[0][1:]] = (x[0][1:],) + x[1:]
- return cnf
+ return self._getconfigure(_flatten((self._w, cmd)))
if isinstance(cnf, str):
- x = self.tk.split(
- self.tk.call(_flatten((self._w, cmd, '-'+cnf))))
- return (x[0][1:],) + x[1:]
+ return self._getconfigure1(_flatten((self._w, cmd, '-'+cnf)))
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
# These used to be defined in Widget:
def configure(self, cnf=None, **kw):
@@ -1258,7 +1278,7 @@ class Misc:
def keys(self):
"""Return a list of all resource names of this widget."""
return [x[0][1:] for x in
- self.tk.split(self.tk.call(self._w, 'configure'))]
+ self.tk.splitlist(self.tk.call(self._w, 'configure'))]
def __str__(self):
"""Return the window path name of this widget."""
return self._w
@@ -1293,6 +1313,13 @@ class Misc:
self.tk.call(
'place', 'slaves', self._w))]
# Grid methods that apply to the master
+ def grid_anchor(self, anchor=None): # new in Tk 8.5
+ """The anchor value controls how to place the grid within the
+ master when no row/column has any weight.
+
+ The default anchor is nw."""
+ self.tk.call('grid', 'anchor', self._w, anchor)
+ anchor = grid_anchor
def grid_bbox(self, column=None, row=None, col2=None, row2=None):
"""Return a tuple of integer coordinates for the bounding
box of this widget controlled by the geometry manager grid.
@@ -1311,8 +1338,22 @@ class Misc:
if col2 is not None and row2 is not None:
args = args + (col2, row2)
return self._getints(self.tk.call(*args)) or None
-
bbox = grid_bbox
+
+ def _gridconvvalue(self, value):
+ if isinstance(value, (str, _tkinter.Tcl_Obj)):
+ try:
+ svalue = str(value)
+ if not svalue:
+ return None
+ elif '.' in svalue:
+ return getdouble(svalue)
+ else:
+ return getint(svalue)
+ except ValueError:
+ pass
+ return value
+
def _grid_configure(self, command, index, cnf, kw):
"""Internal function."""
if isinstance(cnf, str) and not kw:
@@ -1331,22 +1372,14 @@ class Misc:
for i in range(0, len(words), 2):
key = words[i][1:]
value = words[i+1]
- if not value:
- value = None
- elif '.' in value:
- value = getdouble(value)
- else:
- value = getint(value)
- dict[key] = value
+ dict[key] = self._gridconvvalue(value)
return dict
res = self.tk.call(
('grid', command, self._w, index)
+ options)
if len(options) == 1:
- if not res: return None
- # In Tk 7.5, -width can be a float
- if '.' in res: return getdouble(res)
- return getint(res)
+ return self._gridconvvalue(res)
+
def grid_columnconfigure(self, index, cnf={}, **kw):
"""Configure column INDEX of a grid.
@@ -1433,11 +1466,11 @@ class Misc:
def image_names(self):
"""Return a list of all existing image names."""
- return self.tk.call('image', 'names')
+ return self.tk.splitlist(self.tk.call('image', 'names'))
def image_types(self):
"""Return a list of all available image types (e.g. phote bitmap)."""
- return self.tk.call('image', 'types')
+ return self.tk.splitlist(self.tk.call('image', 'types'))
class CallWrapper:
@@ -1551,7 +1584,11 @@ class Wm:
if len(wlist) > 1:
wlist = (wlist,) # Tk needs a list of windows here
args = ('wm', 'colormapwindows', self._w) + wlist
- return [self._nametowidget(x) for x in self.tk.call(args)]
+ if wlist:
+ self.tk.call(args)
+ else:
+ return [self._nametowidget(x)
+ for x in self.tk.splitlist(self.tk.call(args))]
colormapwindows = wm_colormapwindows
def wm_command(self, value=None):
"""Store VALUE in WM_COMMAND property. It is the command
@@ -1570,6 +1607,14 @@ class Wm:
the focus. Return current focus model if MODEL is None."""
return self.tk.call('wm', 'focusmodel', self._w, model)
focusmodel = wm_focusmodel
+ def wm_forget(self, window): # new in Tk 8.5
+ """The window will be unmappend from the screen and will no longer
+ be managed by wm. toplevel windows will be treated like frame
+ windows once they are no longer managed by wm, however, the menu
+ option configuration will be remembered and the menus will return
+ once the widget is managed again."""
+ self.tk.call('wm', 'forget', window)
+ forget = wm_forget
def wm_frame(self):
"""Return identifier for decorative frame of this widget if present."""
return self.tk.call('wm', 'frame', self._w)
@@ -1623,6 +1668,31 @@ class Wm:
None is given."""
return self.tk.call('wm', 'iconname', self._w, newName)
iconname = wm_iconname
+ def wm_iconphoto(self, default=False, *args): # new in Tk 8.5
+ """Sets the titlebar icon for this window based on the named photo
+ images passed through args. If default is True, this is applied to
+ all future created toplevels as well.
+
+ The data in the images is taken as a snapshot at the time of
+ invocation. If the images are later changed, this is not reflected
+ to the titlebar icons. Multiple images are accepted to allow
+ different images sizes to be provided. The window manager may scale
+ provided icons to an appropriate size.
+
+ On Windows, the images are packed into a Windows icon structure.
+ This will override an icon specified to wm_iconbitmap, and vice
+ versa.
+
+ On X, the images are arranged into the _NET_WM_ICON X property,
+ which most modern window managers support. An icon specified by
+ wm_iconbitmap may exist simuultaneously.
+
+ On Macintosh, this currently does nothing."""
+ if default:
+ self.tk.call('wm', 'iconphoto', self._w, "-default", *args)
+ else:
+ self.tk.call('wm', 'iconphoto', self._w, *args)
+ iconphoto = wm_iconphoto
def wm_iconposition(self, x=None, y=None):
"""Set the position of the icon of this widget to X and Y. Return
a tuple of the current values of X and X if None is given."""
@@ -1634,6 +1704,12 @@ class Wm:
value if None is given."""
return self.tk.call('wm', 'iconwindow', self._w, pathName)
iconwindow = wm_iconwindow
+ def wm_manage(self, widget): # new in Tk 8.5
+ """The widget specified will become a stand alone top-level window.
+ The window will be decorated with the window managers title bar,
+ etc."""
+ self.tk.call('wm', 'manage', widget)
+ manage = wm_manage
def wm_maxsize(self, width=None, height=None):
"""Set max WIDTH and HEIGHT for this widget. If the window is gridded
the values are given in grid units. Return the current values if None
@@ -1798,7 +1874,7 @@ class Tk(Misc, Wm):
exec(open(base_py).read(), dir)
def report_callback_exception(self, exc, val, tb):
"""Internal function. It reports exception on sys.stderr."""
- import traceback, sys
+ import traceback
sys.stderr.write("Exception in Tkinter callback\n")
sys.last_type = exc
sys.last_value = val
@@ -1863,7 +1939,7 @@ class Pack:
for i in range(0, len(words), 2):
key = words[i][1:]
value = words[i+1]
- if value[:1] == '.':
+ if str(value)[:1] == '.':
value = self._nametowidget(value)
dict[key] = value
return dict
@@ -1914,7 +1990,7 @@ class Place:
for i in range(0, len(words), 2):
key = words[i][1:]
value = words[i+1]
- if value[:1] == '.':
+ if str(value)[:1] == '.':
value = self._nametowidget(value)
dict[key] = value
return dict
@@ -1963,7 +2039,7 @@ class Grid:
for i in range(0, len(words), 2):
key = words[i][1:]
value = words[i+1]
- if value[:1] == '.':
+ if str(value)[:1] == '.':
value = self._nametowidget(value)
dict[key] = value
return dict
@@ -2123,25 +2199,45 @@ class Button(Widget):
"""
return self.tk.call(self._w, 'invoke')
+
# Indices:
# XXX I don't like these -- take them away
def AtEnd():
+ warnings.warn("tkinter.AtEnd will be removed in 3.4",
+ DeprecationWarning, stacklevel=2)
return 'end'
+
+
def AtInsert(*args):
+ warnings.warn("tkinter.AtInsert will be removed in 3.4",
+ DeprecationWarning, stacklevel=2)
s = 'insert'
for a in args:
if a: s = s + (' ' + a)
return s
+
+
def AtSelFirst():
+ warnings.warn("tkinter.AtSelFirst will be removed in 3.4",
+ DeprecationWarning, stacklevel=2)
return 'sel.first'
+
+
def AtSelLast():
+ warnings.warn("tkinter.AtSelLast will be removed in 3.4",
+ DeprecationWarning, stacklevel=2)
return 'sel.last'
+
+
def At(x, y=None):
+ warnings.warn("tkinter.At will be removed in 3.4",
+ DeprecationWarning, stacklevel=2)
if y is None:
return '@%r' % (x,)
else:
return '@%r,%r' % (x, y)
+
class Canvas(Widget, XView, YView):
"""Canvas widget to display graphical elements like lines or text."""
def __init__(self, master=None, cnf={}, **kw):
@@ -2727,6 +2823,10 @@ class Menu(Widget):
def unpost(self):
"""Unmap a menu."""
self.tk.call(self._w, 'unpost')
+ def xposition(self, index): # new in Tk 8.5
+ """Return the x-position of the leftmost pixel of the menu item
+ at INDEX."""
+ return getint(self.tk.call(self._w, 'xposition', index))
def yposition(self, index):
"""Return the y-position of the topmost pixel of the menu item at INDEX."""
return getint(self.tk.call(
@@ -2886,11 +2986,31 @@ class Text(Widget, XView, YView):
relation OP is satisfied. OP is one of <, <=, ==, >=, >, or !=."""
return self.tk.getboolean(self.tk.call(
self._w, 'compare', index1, op, index2))
+ def count(self, index1, index2, *args): # new in Tk 8.5
+ """Counts the number of relevant things between the two indices.
+ If index1 is after index2, the result will be a negative number
+ (and this holds for each of the possible options).
+
+ The actual items which are counted depends on the options given by
+ args. The result is a list of integers, one for the result of each
+ counting option given. Valid counting options are "chars",
+ "displaychars", "displayindices", "displaylines", "indices",
+ "lines", "xpixels" and "ypixels". There is an additional possible
+ option "update", which if given then all subsequent options ensure
+ that any possible out of date information is recalculated."""
+ args = ['-%s' % arg for arg in args if not arg.startswith('-')]
+ args += [index1, index2]
+ res = self.tk.call(self._w, 'count', *args) or None
+ if res is not None and len(args) <= 3:
+ return (res, )
+ else:
+ return res
def debug(self, boolean=None):
"""Turn on the internal consistency checks of the B-Tree inside the text
widget according to BOOLEAN."""
- return self.tk.getboolean(self.tk.call(
- self._w, 'debug', boolean))
+ if boolean is None:
+ return self.tk.getboolean(self.tk.call(self._w, 'debug'))
+ self.tk.call(self._w, 'debug', boolean)
def delete(self, index1, index2=None):
"""Delete the characters between INDEX1 and INDEX2 (not included)."""
self.tk.call(self._w, 'delete', index1, index2)
@@ -3048,6 +3168,24 @@ class Text(Widget, XView, YView):
def mark_previous(self, index):
"""Return the name of the previous mark before INDEX."""
return self.tk.call(self._w, 'mark', 'previous', index) or None
+ def peer_create(self, newPathName, cnf={}, **kw): # new in Tk 8.5
+ """Creates a peer text widget with the given newPathName, and any
+ optional standard configuration options. By default the peer will
+ have the same start and end line as the parent widget, but
+ these can be overriden with the standard configuration options."""
+ self.tk.call(self._w, 'peer', 'create', newPathName,
+ *self._options(cnf, kw))
+ def peer_names(self): # new in Tk 8.5
+ """Returns a list of peers of this widget (this does not include
+ the widget itself)."""
+ return self.tk.splitlist(self.tk.call(self._w, 'peer', 'names'))
+ def replace(self, index1, index2, chars, *args): # new in Tk 8.5
+ """Replaces the range of characters between index1 and index2 with
+ the given characters and tags specified by args.
+
+ See the method insert for some more information about args, and the
+ method delete for information about the indices."""
+ self.tk.call(self._w, 'replace', index1, index2, chars, *args)
def scan_mark(self, x, y):
"""Remember the current X, Y coordinates."""
self.tk.call(self._w, 'scan', 'mark', x, y)
@@ -3345,8 +3483,11 @@ class BitmapImage(Image):
Valid resource names: background, data, file, foreground, maskdata, maskfile."""
Image.__init__(self, 'bitmap', name, cnf, master, **kw)
-def image_names(): return _default_root.tk.call('image', 'names')
-def image_types(): return _default_root.tk.call('image', 'types')
+def image_names():
+ return _default_root.tk.splitlist(_default_root.tk.call('image', 'names'))
+
+def image_types():
+ return _default_root.tk.splitlist(_default_root.tk.call('image', 'types'))
class Spinbox(Widget, XView):
@@ -3392,7 +3533,7 @@ class Spinbox(Widget, XView):
bounding box may refer to a region outside the
visible area of the window.
"""
- return self.tk.call(self._w, 'bbox', index)
+ return self._getints(self.tk.call(self._w, 'bbox', index)) or None
def delete(self, first, last=None):
"""Delete one or more elements of the spinbox.
@@ -3705,23 +3846,17 @@ class PanedWindow(Widget):
"""
if cnf is None and not kw:
- cnf = {}
- for x in self.tk.split(
- self.tk.call(self._w,
- 'paneconfigure', tagOrId)):
- cnf[x[0][1:]] = (x[0][1:],) + x[1:]
- return cnf
+ return self._getconfigure(self._w, 'paneconfigure', tagOrId)
if isinstance(cnf, str) and not kw:
- x = self.tk.split(self.tk.call(
- self._w, 'paneconfigure', tagOrId, '-'+cnf))
- return (x[0][1:],) + x[1:]
+ return self._getconfigure1(
+ self._w, 'paneconfigure', tagOrId, '-'+cnf)
self.tk.call((self._w, 'paneconfigure', tagOrId) +
self._options(cnf, kw))
paneconfig = paneconfigure
def panes(self):
"""Returns an ordered list of the child panes."""
- return self.tk.call(self._w, 'panes')
+ return self.tk.splitlist(self.tk.call(self._w, 'panes'))
######################################################################
# Extensions: