From 999b0e638a1f3311d804334944f648487100339e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 14 Jan 2026 19:32:46 +0200 Subject: [PATCH] gh-143754: Add Tkinter methods pack_content(), place_content() and grid_content() They use Tk commands with new name like "pack content instead of old "pack slaves". --- Doc/whatsnew/3.15.rst | 6 ++ .../test_tkinter/test_geometry_managers.py | 66 ++++++++++++++----- Lib/tkinter/__init__.py | 46 ++++++++++++- ...-01-14-20-35-40.gh-issue-143754.m2NQXA.rst | 3 + 4 files changed, 102 insertions(+), 19 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index b7a27d5db63875..1dd66065b0f93d 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -792,6 +792,12 @@ tkinter using Tcl's ``-all`` and ``-overlap`` options. (Contributed by Rihaan Meher in :gh:`130848`) +* Added new methods :meth:`!pack_content`, :meth:`!place_content` and + :meth:`!grid_content` which use Tk commands with new names (introduced + in Tk 8.6) instead of :meth:`!*_slaves` methods which use Tk commands + with outdated names. + (Contributed by Serhiy Storchaka in :gh:`143754`) + types ------ diff --git a/Lib/test/test_tkinter/test_geometry_managers.py b/Lib/test/test_tkinter/test_geometry_managers.py index b2ce143ff0948f..3dcdadd1aacf10 100644 --- a/Lib/test/test_tkinter/test_geometry_managers.py +++ b/Lib/test/test_tkinter/test_geometry_managers.py @@ -40,11 +40,11 @@ def test_pack_configure_after(self): b.pack_configure(side='top') c.pack_configure(side='top') d.pack_configure(side='top') - self.assertEqual(pack.pack_slaves(), [a, b, c, d]) + self.assertEqual(pack.pack_content(), [a, b, c, d]) a.pack_configure(after=b) - self.assertEqual(pack.pack_slaves(), [b, a, c, d]) + self.assertEqual(pack.pack_content(), [b, a, c, d]) a.pack_configure(after=a) - self.assertEqual(pack.pack_slaves(), [b, a, c, d]) + self.assertEqual(pack.pack_content(), [b, a, c, d]) def test_pack_configure_anchor(self): pack, a, b, c, d = self.create2() @@ -73,11 +73,11 @@ def test_pack_configure_before(self): b.pack_configure(side='top') c.pack_configure(side='top') d.pack_configure(side='top') - self.assertEqual(pack.pack_slaves(), [a, b, c, d]) + self.assertEqual(pack.pack_content(), [a, b, c, d]) a.pack_configure(before=d) - self.assertEqual(pack.pack_slaves(), [b, c, a, d]) + self.assertEqual(pack.pack_content(), [b, c, a, d]) a.pack_configure(before=a) - self.assertEqual(pack.pack_slaves(), [b, c, a, d]) + self.assertEqual(pack.pack_content(), [b, c, a, d]) def test_pack_configure_expand(self): pack, a, b, c, d = self.create2() @@ -110,10 +110,10 @@ def test_pack_configure_in(self): c.pack_configure(side='top') d.pack_configure(side='top') a.pack_configure(in_=pack) - self.assertEqual(pack.pack_slaves(), [b, c, d, a]) + self.assertEqual(pack.pack_content(), [b, c, d, a]) a.pack_configure(in_=c) - self.assertEqual(pack.pack_slaves(), [b, c, d]) - self.assertEqual(c.pack_slaves(), [a]) + self.assertEqual(pack.pack_content(), [b, c, d]) + self.assertEqual(c.pack_content(), [a]) with self.assertRaisesRegex( TclError, """can't pack "?%s"? inside itself""" % (a,)): a.pack_configure(in_=a) @@ -223,11 +223,11 @@ def test_pack_forget(self): a.pack_configure() b.pack_configure() c.pack_configure() - self.assertEqual(pack.pack_slaves(), [a, b, c]) + self.assertEqual(pack.pack_content(), [a, b, c]) b.pack_forget() - self.assertEqual(pack.pack_slaves(), [a, c]) + self.assertEqual(pack.pack_content(), [a, c]) b.pack_forget() - self.assertEqual(pack.pack_slaves(), [a, c]) + self.assertEqual(pack.pack_content(), [a, c]) d.pack_forget() def test_pack_info(self): @@ -273,6 +273,14 @@ def test_pack_propagate(self): self.assertEqual(pack.winfo_reqwidth(), 20) self.assertEqual(pack.winfo_reqheight(), 40) + def test_pack_content(self): + pack, a, b, c, d = self.create2() + self.assertEqual(pack.pack_content(), []) + a.pack_configure() + self.assertEqual(pack.pack_content(), [a]) + b.pack_configure() + self.assertEqual(pack.pack_content(), [a, b]) + def test_pack_slaves(self): pack, a, b, c, d = self.create2() self.assertEqual(pack.pack_slaves(), []) @@ -477,6 +485,15 @@ def test_place_info(self): with self.assertRaises(TypeError): f2.place_info(0) + def test_place_content(self): + foo = tkinter.Frame(self.root) + bar = tkinter.Frame(self.root) + self.assertEqual(foo.place_content(), []) + bar.place_configure(in_=foo) + self.assertEqual(foo.place_content(), [bar]) + with self.assertRaises(TypeError): + foo.place_content(0) + def test_place_slaves(self): foo = tkinter.Frame(self.root) bar = tkinter.Frame(self.root) @@ -729,10 +746,10 @@ def test_grid_forget(self): c = tkinter.Button(self.root) b.grid_configure(row=2, column=2, rowspan=2, columnspan=2, padx=3, pady=4, sticky='ns') - self.assertEqual(self.root.grid_slaves(), [b]) + self.assertEqual(self.root.grid_content(), [b]) b.grid_forget() c.grid_forget() - self.assertEqual(self.root.grid_slaves(), []) + self.assertEqual(self.root.grid_content(), []) self.assertEqual(b.grid_info(), {}) b.grid_configure(row=0, column=0) info = b.grid_info() @@ -749,10 +766,10 @@ def test_grid_remove(self): c = tkinter.Button(self.root) b.grid_configure(row=2, column=2, rowspan=2, columnspan=2, padx=3, pady=4, sticky='ns') - self.assertEqual(self.root.grid_slaves(), [b]) + self.assertEqual(self.root.grid_content(), [b]) b.grid_remove() c.grid_remove() - self.assertEqual(self.root.grid_slaves(), []) + self.assertEqual(self.root.grid_content(), []) self.assertEqual(b.grid_info(), {}) b.grid_configure(row=0, column=0) info = b.grid_info() @@ -887,6 +904,23 @@ def test_grid_size(self): f.grid_configure(row=4, column=5) self.assertEqual(self.root.grid_size(), (6, 5)) + def test_grid_content(self): + self.assertEqual(self.root.grid_content(), []) + a = tkinter.Label(self.root) + a.grid_configure(row=0, column=1) + b = tkinter.Label(self.root) + b.grid_configure(row=1, column=0) + c = tkinter.Label(self.root) + c.grid_configure(row=1, column=1) + d = tkinter.Label(self.root) + d.grid_configure(row=1, column=1) + self.assertEqual(self.root.grid_content(), [d, c, b, a]) + self.assertEqual(self.root.grid_content(row=0), [a]) + self.assertEqual(self.root.grid_content(row=1), [d, c, b]) + self.assertEqual(self.root.grid_content(column=0), [b]) + self.assertEqual(self.root.grid_content(column=1), [d, c, a]) + self.assertEqual(self.root.grid_content(row=1, column=1), [d, c]) + def test_grid_slaves(self): self.assertEqual(self.root.grid_slaves(), []) a = tkinter.Label(self.root) diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index be150e2b892e4b..d695e3ec9cb1b4 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -1885,9 +1885,21 @@ def pack_propagate(self, flag=_noarg_): propagate = pack_propagate - def pack_slaves(self): + def pack_content(self): """Returns a list of all of the content widgets in the packing order for this container.""" + try: + res = self.tk.call('pack', 'content', self._w) + except TclError: + if self.info_patchlevel() >= (8, 6): + raise + res = self.tk.call('pack', 'slaves', self._w) + return [self._nametowidget(x) for x in self.tk.splitlist(res)] + + content = pack_content + + def pack_slaves(self): + """Synonym for pack_content().""" return [self._nametowidget(x) for x in self.tk.splitlist( self.tk.call('pack', 'slaves', self._w))] @@ -1895,9 +1907,19 @@ def pack_slaves(self): slaves = pack_slaves # Place method that applies to the container widget - def place_slaves(self): + def place_content(self): """Returns a list of all the content widgets for which this widget is the container.""" + try: + res = self.tk.call('place', 'content', self._w) + except TclError: + if self.info_patchlevel() >= (8, 6): + raise + res = self.tk.call('place', 'slaves', self._w) + return [self._nametowidget(x) for x in self.tk.splitlist(res)] + + def place_slaves(self): + """Synonym for place_content().""" return [self._nametowidget(x) for x in self.tk.splitlist( self.tk.call( @@ -2018,7 +2040,7 @@ def grid_size(self): size = grid_size - def grid_slaves(self, row=None, column=None): + def grid_content(self, row=None, column=None): """Returns a list of the content widgets. If no arguments are supplied, a list of all of the content in this @@ -2027,6 +2049,21 @@ def grid_slaves(self, row=None, column=None): column is returned. """ args = () + if row is not None: + args = args + ('-row', row) + if column is not None: + args = args + ('-column', column) + try: + res = self.tk.call('grid', 'content', self._w, *args) + except TclError: + if self.info_patchlevel() >= (8, 6): + raise + res = self.tk.call('grid', 'slaves', self._w, *args) + return [self._nametowidget(x) for x in self.tk.splitlist(res)] + + def grid_slaves(self, row=None, column=None): + """Synonym for grid_content().""" + args = () if row is not None: args = args + ('-row', row) if column is not None: @@ -2641,6 +2678,7 @@ def pack_info(self): info = pack_info propagate = pack_propagate = Misc.pack_propagate + content = pack_content = Misc.pack_content slaves = pack_slaves = Misc.pack_slaves @@ -2698,6 +2736,7 @@ def place_info(self): return d info = place_info + content = place_content = Misc.place_content slaves = place_slaves = Misc.place_slaves @@ -2753,6 +2792,7 @@ def grid_info(self): propagate = grid_propagate = Misc.grid_propagate rowconfigure = grid_rowconfigure = Misc.grid_rowconfigure size = grid_size = Misc.grid_size + content = grid_content = Misc.grid_content slaves = grid_slaves = Misc.grid_slaves diff --git a/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst b/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst new file mode 100644 index 00000000000000..edfdd109400d08 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst @@ -0,0 +1,3 @@ +Add new :mod:`tkinter` widget methods :meth:`!pack_content`, +:meth:`!place_content` and :meth:`!grid_content` which are alternative +spelling of old :meth:`!*_slaves` methods.