summaryrefslogtreecommitdiff
path: root/Lib/tkinter
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/tkinter')
-rw-r--r--Lib/tkinter/__init__.py218
-rw-r--r--Lib/tkinter/commondialog.py5
-rw-r--r--Lib/tkinter/dialog.py5
-rw-r--r--Lib/tkinter/test/runtktests.py2
-rw-r--r--Lib/tkinter/test/test_tkinter/test_misc.py8
-rw-r--r--Lib/tkinter/test/test_tkinter/test_variables.py52
-rw-r--r--Lib/tkinter/test/test_tkinter/test_widgets.py7
-rw-r--r--Lib/tkinter/test/test_ttk/test_functions.py1
-rw-r--r--Lib/tkinter/test/test_ttk/test_widgets.py49
-rw-r--r--Lib/tkinter/tix.py36
-rw-r--r--Lib/tkinter/ttk.py66
11 files changed, 349 insertions, 100 deletions
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 1eaab44bfe..ee2415da72 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -30,6 +30,7 @@ button.pack(side=BOTTOM)
tk.mainloop()
"""
+import enum
import sys
import _tkinter # If this fails your Python may not be configured for Tk
@@ -132,6 +133,50 @@ def _splitdict(tk, v, cut_minus=True, conv=None):
dict[key] = value
return dict
+
+class EventType(str, enum.Enum):
+ KeyPress = '2'
+ Key = KeyPress,
+ KeyRelease = '3'
+ ButtonPress = '4'
+ Button = ButtonPress,
+ ButtonRelease = '5'
+ Motion = '6'
+ Enter = '7'
+ Leave = '8'
+ FocusIn = '9'
+ FocusOut = '10'
+ Keymap = '11' # undocumented
+ Expose = '12'
+ GraphicsExpose = '13' # undocumented
+ NoExpose = '14' # undocumented
+ Visibility = '15'
+ Create = '16'
+ Destroy = '17'
+ Unmap = '18'
+ Map = '19'
+ MapRequest = '20'
+ Reparent = '21'
+ Configure = '22'
+ ConfigureRequest = '23'
+ Gravity = '24'
+ ResizeRequest = '25'
+ Circulate = '26'
+ CirculateRequest = '27'
+ Property = '28'
+ SelectionClear = '29' # undocumented
+ SelectionRequest = '30' # undocumented
+ Selection = '31' # undocumented
+ Colormap = '32'
+ ClientMessage = '33' # undocumented
+ Mapping = '34' # undocumented
+ VirtualEvent = '35', # undocumented
+ Activate = '36',
+ Deactivate = '37',
+ MouseWheel = '38',
+ def __str__(self):
+ return self.name
+
class Event:
"""Container for the properties of an event.
@@ -174,7 +219,43 @@ class Event:
widget - widget in which the event occurred
delta - delta of wheel movement (MouseWheel)
"""
- pass
+ def __repr__(self):
+ attrs = {k: v for k, v in self.__dict__.items() if v != '??'}
+ if not self.char:
+ del attrs['char']
+ elif self.char != '??':
+ attrs['char'] = repr(self.char)
+ if not getattr(self, 'send_event', True):
+ del attrs['send_event']
+ if self.state == 0:
+ del attrs['state']
+ elif isinstance(self.state, int):
+ state = self.state
+ mods = ('Shift', 'Lock', 'Control',
+ 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5',
+ 'Button1', 'Button2', 'Button3', 'Button4', 'Button5')
+ s = []
+ for i, n in enumerate(mods):
+ if state & (1 << i):
+ s.append(n)
+ state = state & ~((1<< len(mods)) - 1)
+ if state or not s:
+ s.append(hex(state))
+ attrs['state'] = '|'.join(s)
+ if self.delta == 0:
+ del attrs['delta']
+ # widget usually is known
+ # serial and time are not very interesting
+ # keysym_num duplicates keysym
+ # x_root and y_root mostly duplicate x and y
+ keys = ('send_event',
+ 'state', 'keysym', 'keycode', 'char',
+ 'num', 'delta', 'focus',
+ 'x', 'y', 'width', 'height')
+ return '<%s event%s>' % (
+ self.type,
+ ''.join(' %s=%s' % (k, attrs[k]) for k in keys if k in attrs)
+ )
_support_default_root = 1
_default_root = None
@@ -262,15 +343,8 @@ class Variable:
def get(self):
"""Return value of variable."""
return self._tk.globalgetvar(self._name)
- def trace_variable(self, mode, callback):
- """Define a trace callback for the variable.
- MODE is one of "r", "w", "u" for read, write, undefine.
- CALLBACK must be a function which is called when
- the variable is read, written or undefined.
-
- Return the name of the callback.
- """
+ def _register(self, callback):
f = CallWrapper(callback, None, self._root).__call__
cbname = repr(id(f))
try:
@@ -285,18 +359,80 @@ class Variable:
if self._tclCommands is None:
self._tclCommands = []
self._tclCommands.append(cbname)
+ return cbname
+
+ def trace_add(self, mode, callback):
+ """Define a trace callback for the variable.
+
+ Mode is one of "read", "write", "unset", or a list or tuple of
+ such strings.
+ Callback must be a function which is called when the variable is
+ read, written or unset.
+
+ Return the name of the callback.
+ """
+ cbname = self._register(callback)
+ self._tk.call('trace', 'add', 'variable',
+ self._name, mode, (cbname,))
+ return cbname
+
+ def trace_remove(self, mode, cbname):
+ """Delete the trace callback for a variable.
+
+ Mode is one of "read", "write", "unset" or a list or tuple of
+ such strings. Must be same as were specified in trace_add().
+ cbname is the name of the callback returned from trace_add().
+ """
+ self._tk.call('trace', 'remove', 'variable',
+ self._name, mode, cbname)
+ for m, ca in self.trace_info():
+ if self._tk.splitlist(ca)[0] == cbname:
+ break
+ else:
+ self._tk.deletecommand(cbname)
+ try:
+ self._tclCommands.remove(cbname)
+ except ValueError:
+ pass
+
+ def trace_info(self):
+ """Return all trace callback information."""
+ splitlist = self._tk.splitlist
+ return [(splitlist(k), v) for k, v in map(splitlist,
+ splitlist(self._tk.call('trace', 'info', 'variable', self._name)))]
+
+ def trace_variable(self, mode, callback):
+ """Define a trace callback for the variable.
+
+ MODE is one of "r", "w", "u" for read, write, undefine.
+ CALLBACK must be a function which is called when
+ the variable is read, written or undefined.
+
+ Return the name of the callback.
+
+ This deprecated method wraps a deprecated Tcl method that will
+ likely be removed in the future. Use trace_add() instead.
+ """
+ # TODO: Add deprecation warning
+ cbname = self._register(callback)
self._tk.call("trace", "variable", self._name, mode, cbname)
return cbname
+
trace = trace_variable
+
def trace_vdelete(self, mode, cbname):
"""Delete the trace callback for a variable.
MODE is one of "r", "w", "u" for read, write, undefine.
CBNAME is the name of the callback returned from trace_variable or trace.
+
+ This deprecated method wraps a deprecated Tcl method that will
+ likely be removed in the future. Use trace_remove() instead.
"""
+ # TODO: Add deprecation warning
self._tk.call("trace", "vdelete", self._name, mode, cbname)
cbname = self._tk.splitlist(cbname)[0]
- for m, ca in self.trace_vinfo():
+ for m, ca in self.trace_info():
if self._tk.splitlist(ca)[0] == cbname:
break
else:
@@ -305,10 +441,17 @@ class Variable:
self._tclCommands.remove(cbname)
except ValueError:
pass
+
def trace_vinfo(self):
- """Return all trace callback information."""
+ """Return all trace callback information.
+
+ This deprecated method wraps a deprecated Tcl method that will
+ likely be removed in the future. Use trace_info() instead.
+ """
+ # TODO: Add deprecation warning
return [self._tk.splitlist(x) for x in self._tk.splitlist(
self._tk.call("trace", "vinfo", self._name))]
+
def __eq__(self, other):
"""Comparison for equality (==).
@@ -430,6 +573,9 @@ class Misc:
Base class which defines methods common for interior widgets."""
+ # used for generating child widget names
+ _last_child_ids = None
+
# XXX font command?
_tclCommands = None
def destroy(self):
@@ -477,12 +623,6 @@ class Misc:
disabledForeground, insertBackground, troughColor."""
self.tk.call(('tk_setPalette',)
+ _flatten(args) + _flatten(list(kw.items())))
- def tk_menuBar(self, *args):
- """Do not use. Needed in Tk 3.6 and earlier."""
- # obsolete since Tk 4.0
- import warnings
- warnings.warn('tk_menuBar() does nothing and will be removed in 3.6',
- DeprecationWarning, stacklevel=2)
def wait_variable(self, name='PY_VAR'):
"""Wait until the variable is modified.
@@ -854,8 +994,7 @@ class Misc:
self.tk.call('winfo', 'height', self._w))
def winfo_id(self):
"""Return identifier ID for this widget."""
- return self.tk.getint(
- self.tk.call('winfo', 'id', self._w))
+ return int(self.tk.call('winfo', 'id', self._w), 0)
def winfo_interps(self, displayof=0):
"""Return the name of all Tcl interpreters for this display."""
args = ('winfo', 'interps') + self._displayof(displayof)
@@ -975,18 +1114,16 @@ class Misc:
def winfo_visualid(self):
"""Return the X identifier for the visual for this widget."""
return self.tk.call('winfo', 'visualid', self._w)
- def winfo_visualsavailable(self, includeids=0):
+ def winfo_visualsavailable(self, includeids=False):
"""Return a list of all visuals available for the screen
of this widget.
Each item in the list consists of a visual name (see winfo_visual), a
- depth and if INCLUDEIDS=1 is given also the X identifier."""
- data = self.tk.split(
- self.tk.call('winfo', 'visualsavailable', self._w,
- includeids and 'includeids' or None))
- if isinstance(data, str):
- data = [self.tk.split(data)]
- return [self.__winfo_parseitem(x) for x in data]
+ depth and if includeids is true is given also the X identifier."""
+ data = self.tk.call('winfo', 'visualsavailable', self._w,
+ 'includeids' if includeids else None)
+ data = [self.tk.splitlist(x) for x in self.tk.splitlist(data)]
+ return [self.__winfo_parseitem(x) for x in data]
def __winfo_parseitem(self, t):
"""Internal function."""
return t[:1] + tuple(map(self.__winfo_getint, t[1:]))
@@ -1287,7 +1424,10 @@ class Misc:
except TclError: pass
e.keysym = K
e.keysym_num = getint_event(N)
- e.type = T
+ try:
+ e.type = EventType(T)
+ except ValueError:
+ e.type = T
try:
e.widget = self._nametowidget(W)
except KeyError:
@@ -1897,9 +2037,6 @@ class Tk(Misc, Wm):
if tcl_version != _tkinter.TCL_VERSION:
raise RuntimeError("tcl.h version (%s) doesn't match libtcl.a version (%s)" \
% (_tkinter.TCL_VERSION, tcl_version))
- if TkVersion < 4.0:
- raise RuntimeError("Tk 4.0 or higher is required; found Tk %s"
- % str(TkVersion))
# Create and register the tkerror and exit commands
# We need to inline parts of _register here, _ register
# would register differently-named commands.
@@ -2122,7 +2259,15 @@ class BaseWidget(Misc):
name = cnf['name']
del cnf['name']
if not name:
- name = repr(id(self))
+ name = self.__class__.__name__.lower()
+ if master._last_child_ids is None:
+ master._last_child_ids = {}
+ count = master._last_child_ids.get(name, 0) + 1
+ master._last_child_ids[name] = count
+ if count == 1:
+ name = '!%s' % (name,)
+ else:
+ name = '!%s%d' % (name, count)
self._name = name
if master._w=='.':
self._w = '.' + name
@@ -2718,12 +2863,6 @@ class Menu(Widget):
def tk_popup(self, x, y, entry=""):
"""Post the menu at position X,Y with entry ENTRY."""
self.tk.call('tk_popup', self._w, x, y, entry)
- def tk_bindForTraversal(self):
- # obsolete since Tk 4.0
- import warnings
- warnings.warn('tk_bindForTraversal() does nothing and '
- 'will be removed in 3.6',
- DeprecationWarning, stacklevel=2)
def activate(self, index):
"""Activate entry at INDEX."""
self.tk.call(self._w, 'activate', index)
@@ -3346,9 +3485,6 @@ class Image:
if not name:
Image._last_id += 1
name = "pyimage%r" % (Image._last_id,) # tk itself would use image<x>
- # The following is needed for systems where id(x)
- # can return a negative number, such as Linux/m68k:
- if name[0] == '-': name = '_' + name[1:]
if kw and cnf: cnf = _cnfmerge((cnf, kw))
elif kw: cnf = kw
options = ()
diff --git a/Lib/tkinter/commondialog.py b/Lib/tkinter/commondialog.py
index d2688dba9b..1e75cae689 100644
--- a/Lib/tkinter/commondialog.py
+++ b/Lib/tkinter/commondialog.py
@@ -15,11 +15,6 @@ class Dialog:
command = None
def __init__(self, master=None, **options):
-
- # FIXME: should this be placed on the module level instead?
- if TkVersion < 4.2:
- raise TclError("this module requires Tk 4.2 or newer")
-
self.master = master
self.options = options
if not master and options.get('parent'):
diff --git a/Lib/tkinter/dialog.py b/Lib/tkinter/dialog.py
index be085abe1d..f61c5f7fa9 100644
--- a/Lib/tkinter/dialog.py
+++ b/Lib/tkinter/dialog.py
@@ -3,10 +3,7 @@
from tkinter import *
from tkinter import _cnfmerge
-if TkVersion <= 3.6:
- DIALOG_ICON = 'warning'
-else:
- DIALOG_ICON = 'questhead'
+DIALOG_ICON = 'questhead'
class Dialog(Widget):
diff --git a/Lib/tkinter/test/runtktests.py b/Lib/tkinter/test/runtktests.py
index dbe5e88c14..33dc54a137 100644
--- a/Lib/tkinter/test/runtktests.py
+++ b/Lib/tkinter/test/runtktests.py
@@ -7,8 +7,6 @@ Extensions also should live in packages following the same rule as above.
"""
import os
-import sys
-import unittest
import importlib
import test.support
diff --git a/Lib/tkinter/test/test_tkinter/test_misc.py b/Lib/tkinter/test/test_tkinter/test_misc.py
index 85ee2c70b1..9dc1e37547 100644
--- a/Lib/tkinter/test/test_tkinter/test_misc.py
+++ b/Lib/tkinter/test/test_tkinter/test_misc.py
@@ -12,6 +12,14 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
f = tkinter.Frame(t, name='child')
self.assertEqual(repr(f), '<tkinter.Frame object .top.child>')
+ def test_generated_names(self):
+ t = tkinter.Toplevel(self.root)
+ f = tkinter.Frame(t)
+ f2 = tkinter.Frame(t)
+ b = tkinter.Button(f2)
+ for name in str(b).split('.'):
+ self.assertFalse(name.isidentifier(), msg=repr(name))
+
def test_tk_setPalette(self):
root = self.root
root.tk_setPalette('black')
diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py
index d8ba9cea74..2eb1e12671 100644
--- a/Lib/tkinter/test/test_tkinter/test_variables.py
+++ b/Lib/tkinter/test/test_tkinter/test_variables.py
@@ -87,7 +87,8 @@ class TestVariable(TestBase):
v.set("value")
self.assertTrue(v.side_effect)
- def test_trace(self):
+ def test_trace_old(self):
+ # Old interface
v = Variable(self.root)
vname = str(v)
trace = []
@@ -136,6 +137,55 @@ class TestVariable(TestBase):
gc.collect()
self.assertEqual(trace, [('write', vname, '', 'u')])
+ def test_trace(self):
+ v = Variable(self.root)
+ vname = str(v)
+ trace = []
+ def read_tracer(*args):
+ trace.append(('read',) + args)
+ def write_tracer(*args):
+ trace.append(('write',) + args)
+ tr1 = v.trace_add('read', read_tracer)
+ tr2 = v.trace_add(['write', 'unset'], write_tracer)
+ self.assertEqual(sorted(v.trace_info()), [
+ (('read',), tr1),
+ (('write', 'unset'), tr2)])
+ self.assertEqual(trace, [])
+
+ v.set('spam')
+ self.assertEqual(trace, [('write', vname, '', 'write')])
+
+ trace = []
+ v.get()
+ self.assertEqual(trace, [('read', vname, '', 'read')])
+
+ trace = []
+ info = sorted(v.trace_info())
+ v.trace_remove('write', tr1) # Wrong mode
+ self.assertEqual(sorted(v.trace_info()), info)
+ with self.assertRaises(TclError):
+ v.trace_remove('read', 'spam') # Wrong command name
+ self.assertEqual(sorted(v.trace_info()), info)
+ v.get()
+ self.assertEqual(trace, [('read', vname, '', 'read')])
+
+ trace = []
+ v.trace_remove('read', tr1)
+ self.assertEqual(v.trace_info(), [(('write', 'unset'), tr2)])
+ v.get()
+ self.assertEqual(trace, [])
+
+ trace = []
+ del write_tracer
+ gc.collect()
+ v.set('eggs')
+ self.assertEqual(trace, [('write', vname, '', 'write')])
+
+ trace = []
+ del v
+ gc.collect()
+ self.assertEqual(trace, [('write', vname, '', 'unset')])
+
class TestStringVar(TestBase):
diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py
index c924d55937..81b52eafea 100644
--- a/Lib/tkinter/test/test_tkinter/test_widgets.py
+++ b/Lib/tkinter/test/test_tkinter/test_widgets.py
@@ -91,9 +91,10 @@ class ToplevelTest(AbstractToplevelTest, unittest.TestCase):
widget = self.create()
self.assertEqual(widget['use'], '')
parent = self.create(container=True)
- wid = parent.winfo_id()
- widget2 = self.create(use=wid)
- self.assertEqual(int(widget2['use']), wid)
+ wid = hex(parent.winfo_id())
+ with self.subTest(wid=wid):
+ widget2 = self.create(use=wid)
+ self.assertEqual(widget2['use'], wid)
@add_standard_options(StandardOptionsTests)
diff --git a/Lib/tkinter/test/test_ttk/test_functions.py b/Lib/tkinter/test/test_ttk/test_functions.py
index c68a650559..a1b7cdfcd1 100644
--- a/Lib/tkinter/test/test_ttk/test_functions.py
+++ b/Lib/tkinter/test/test_ttk/test_functions.py
@@ -1,6 +1,5 @@
# -*- encoding: utf-8 -*-
import unittest
-import tkinter
from tkinter import ttk
class MockTkApp:
diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py
index 8bd22d03e5..26766a8a1f 100644
--- a/Lib/tkinter/test/test_ttk/test_widgets.py
+++ b/Lib/tkinter/test/test_ttk/test_widgets.py
@@ -1487,6 +1487,7 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
def test_selection(self):
+ self.assertRaises(TypeError, self.tv.selection, 'spam')
# item 'none' doesn't exist
self.assertRaises(tkinter.TclError, self.tv.selection_set, 'none')
self.assertRaises(tkinter.TclError, self.tv.selection_add, 'none')
@@ -1500,25 +1501,31 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
c3 = self.tv.insert(item1, 'end')
self.assertEqual(self.tv.selection(), ())
- self.tv.selection_set((c1, item2))
+ self.tv.selection_set(c1, item2)
self.assertEqual(self.tv.selection(), (c1, item2))
self.tv.selection_set(c2)
self.assertEqual(self.tv.selection(), (c2,))
- self.tv.selection_add((c1, item2))
+ self.tv.selection_add(c1, item2)
self.assertEqual(self.tv.selection(), (c1, c2, item2))
self.tv.selection_add(item1)
self.assertEqual(self.tv.selection(), (item1, c1, c2, item2))
+ self.tv.selection_add()
+ self.assertEqual(self.tv.selection(), (item1, c1, c2, item2))
- self.tv.selection_remove((item1, c3))
+ self.tv.selection_remove(item1, c3)
self.assertEqual(self.tv.selection(), (c1, c2, item2))
self.tv.selection_remove(c2)
self.assertEqual(self.tv.selection(), (c1, item2))
+ self.tv.selection_remove()
+ self.assertEqual(self.tv.selection(), (c1, item2))
- self.tv.selection_toggle((c1, c3))
+ self.tv.selection_toggle(c1, c3)
self.assertEqual(self.tv.selection(), (c3, item2))
self.tv.selection_toggle(item2)
self.assertEqual(self.tv.selection(), (c3,))
+ self.tv.selection_toggle()
+ self.assertEqual(self.tv.selection(), (c3,))
self.tv.insert('', 'end', id='with spaces')
self.tv.selection_set('with spaces')
@@ -1536,6 +1543,40 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
self.tv.selection_set(b'bytes\xe2\x82\xac')
self.assertEqual(self.tv.selection(), ('bytes\xe2\x82\xac',))
+ self.tv.selection_set()
+ self.assertEqual(self.tv.selection(), ())
+
+ # Old interface
+ self.tv.selection_set((c1, item2))
+ self.assertEqual(self.tv.selection(), (c1, item2))
+ self.tv.selection_add((c1, item1))
+ self.assertEqual(self.tv.selection(), (item1, c1, item2))
+ self.tv.selection_remove((item1, c3))
+ self.assertEqual(self.tv.selection(), (c1, item2))
+ self.tv.selection_toggle((c1, c3))
+ self.assertEqual(self.tv.selection(), (c3, item2))
+
+ if sys.version_info >= (3, 7):
+ import warnings
+ warnings.warn(
+ 'Deprecated API of Treeview.selection() should be removed')
+ self.tv.selection_set()
+ self.assertEqual(self.tv.selection(), ())
+ with self.assertWarns(DeprecationWarning):
+ self.tv.selection('set', (c1, item2))
+ self.assertEqual(self.tv.selection(), (c1, item2))
+ with self.assertWarns(DeprecationWarning):
+ self.tv.selection('add', (c1, item1))
+ self.assertEqual(self.tv.selection(), (item1, c1, item2))
+ with self.assertWarns(DeprecationWarning):
+ self.tv.selection('remove', (item1, c3))
+ self.assertEqual(self.tv.selection(), (c1, item2))
+ with self.assertWarns(DeprecationWarning):
+ self.tv.selection('toggle', (c1, c3))
+ self.assertEqual(self.tv.selection(), (c3, item2))
+ with self.assertWarns(DeprecationWarning):
+ selection = self.tv.selection(None)
+ self.assertEqual(selection, (c3, item2))
def test_set(self):
self.tv['columns'] = ['A', 'B']
diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py
index a1006bdf84..d9c097a77c 100644
--- a/Lib/tkinter/tix.py
+++ b/Lib/tkinter/tix.py
@@ -27,10 +27,6 @@ import tkinter
from tkinter import *
from tkinter import _cnfmerge
-# WARNING - TkVersion is a limited precision floating point number
-if TkVersion < 3.999:
- raise ImportError("This version of Tix.py requires Tk 4.0 or higher")
-
import _tkinter # If this fails your Python may not be configured for Tk
# Some more constants (for consistency with Tkinter)
@@ -472,16 +468,17 @@ class DisplayStyle:
"""DisplayStyle - handle configuration options shared by
(multiple) Display Items"""
- def __init__(self, itemtype, cnf={}, **kw):
- if 'refwindow' in kw:
- master = kw['refwindow']
- elif 'refwindow' in cnf:
- master = cnf['refwindow']
- else:
- master = tkinter._default_root
- if not master:
- raise RuntimeError("Too early to create display style: "
- "no root window")
+ def __init__(self, itemtype, cnf={}, *, master=None, **kw):
+ if not master:
+ if 'refwindow' in kw:
+ master = kw['refwindow']
+ elif 'refwindow' in cnf:
+ master = cnf['refwindow']
+ else:
+ master = tkinter._default_root
+ if not master:
+ raise RuntimeError("Too early to create display style: "
+ "no root window")
self.tk = master.tk
self.stylename = self.tk.call('tixDisplayStyle', itemtype,
*self._options(cnf,kw) )
@@ -1116,7 +1113,7 @@ class ListNoteBook(TixWidget):
def pages(self):
# Can't call subwidgets_all directly because we don't want .nbframe
- names = self.tk.split(self.tk.call(self._w, 'pages'))
+ names = self.tk.splitlist(self.tk.call(self._w, 'pages'))
ret = []
for x in names:
ret.append(self.subwidget(x))
@@ -1162,7 +1159,7 @@ class NoteBook(TixWidget):
def pages(self):
# Can't call subwidgets_all directly because we don't want .nbframe
- names = self.tk.split(self.tk.call(self._w, 'pages'))
+ names = self.tk.splitlist(self.tk.call(self._w, 'pages'))
ret = []
for x in names:
ret.append(self.subwidget(x))
@@ -1585,8 +1582,7 @@ class CheckList(TixWidget):
'''Returns a list of items whose status matches status. If status is
not specified, the list of items in the "on" status will be returned.
Mode can be on, off, default'''
- c = self.tk.split(self.tk.call(self._w, 'getselection', mode))
- return self.tk.splitlist(c)
+ return self.tk.splitlist(self.tk.call(self._w, 'getselection', mode))
def getstatus(self, entrypath):
'''Returns the current status of entryPath.'''
@@ -1907,7 +1903,7 @@ class Grid(TixWidget, XView, YView):
or a real number following by the word chars
(e.g. 3.4chars) that sets the width of the column to the
given number of characters."""
- return self.tk.split(self.tk.call(self._w, 'size', 'column', index,
+ return self.tk.splitlist(self.tk.call(self._w, 'size', 'column', index,
*self._options({}, kw)))
def size_row(self, index, **kw):
@@ -1932,7 +1928,7 @@ class Grid(TixWidget, XView, YView):
or a real number following by the word chars
(e.g. 3.4chars) that sets the height of the row to the
given number of characters."""
- return self.tk.split(self.tk.call(
+ return self.tk.splitlist(self.tk.call(
self, 'size', 'row', index, *self._options({}, kw)))
def unset(self, x, y):
diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py
index f4a6d8cf54..c474e60713 100644
--- a/Lib/tkinter/ttk.py
+++ b/Lib/tkinter/ttk.py
@@ -28,6 +28,8 @@ __all__ = ["Button", "Checkbutton", "Combobox", "Entry", "Frame", "Label",
import tkinter
from tkinter import _flatten, _join, _stringify, _splitdict
+_sentinel = object()
+
# Verify if Tk is new enough to not need the Tile package
_REQUIRE_TILE = True if tkinter.TkVersion < 8.5 else False
@@ -381,7 +383,9 @@ class Style(object):
a sequence identifying the value for that option."""
if query_opt is not None:
kw[query_opt] = None
- return _val_or_dict(self.tk, kw, self._name, "configure", style)
+ result = _val_or_dict(self.tk, kw, self._name, "configure", style)
+ if result or query_opt:
+ return result
def map(self, style, query_opt=None, **kw):
@@ -466,12 +470,14 @@ class Style(object):
def element_names(self):
"""Returns the list of elements defined in the current theme."""
- return self.tk.splitlist(self.tk.call(self._name, "element", "names"))
+ return tuple(n.lstrip('-') for n in self.tk.splitlist(
+ self.tk.call(self._name, "element", "names")))
def element_options(self, elementname):
"""Return the list of elementname's options."""
- return self.tk.splitlist(self.tk.call(self._name, "element", "options", elementname))
+ return tuple(o.lstrip('-') for o in self.tk.splitlist(
+ self.tk.call(self._name, "element", "options", elementname)))
def theme_create(self, themename, parent=None, settings=None):
@@ -1390,31 +1396,53 @@ class Treeview(Widget, tkinter.XView, tkinter.YView):
self.tk.call(self._w, "see", item)
- def selection(self, selop=None, items=None):
- """If selop is not specified, returns selected items."""
- if isinstance(items, (str, bytes)):
- items = (items,)
+ def selection(self, selop=_sentinel, items=None):
+ """Returns the tuple of selected items."""
+ if selop is _sentinel:
+ selop = None
+ elif selop is None:
+ import warnings
+ warnings.warn(
+ "The selop=None argument of selection() is deprecated "
+ "and will be removed in Python 3.7",
+ DeprecationWarning, 3)
+ elif selop in ('set', 'add', 'remove', 'toggle'):
+ import warnings
+ warnings.warn(
+ "The selop argument of selection() is deprecated "
+ "and will be removed in Python 3.7, "
+ "use selection_%s() instead" % (selop,),
+ DeprecationWarning, 3)
+ else:
+ raise TypeError('Unsupported operation')
return self.tk.splitlist(self.tk.call(self._w, "selection", selop, items))
- def selection_set(self, items):
- """items becomes the new selection."""
- self.selection("set", items)
+ def _selection(self, selop, items):
+ if len(items) == 1 and isinstance(items[0], (tuple, list)):
+ items = items[0]
+
+ self.tk.call(self._w, "selection", selop, items)
+
+
+ def selection_set(self, *items):
+ """The specified items becomes the new selection."""
+ self._selection("set", items)
- def selection_add(self, items):
- """Add items to the selection."""
- self.selection("add", items)
+ def selection_add(self, *items):
+ """Add all of the specified items to the selection."""
+ self._selection("add", items)
- def selection_remove(self, items):
- """Remove items from the selection."""
- self.selection("remove", items)
+ def selection_remove(self, *items):
+ """Remove all of the specified items from the selection."""
+ self._selection("remove", items)
- def selection_toggle(self, items):
- """Toggle the selection state of each item in items."""
- self.selection("toggle", items)
+ def selection_toggle(self, *items):
+ """Toggle the selection state of each specified item."""
+ self._selection("toggle", items)
def set(self, item, column=None, value=None):