diff options
Diffstat (limited to 'Lib/tkinter/__init__.py')
-rw-r--r-- | Lib/tkinter/__init__.py | 253 |
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: |