mirror of
https://github.com/python/cpython.git
synced 2026-06-27 19:36:07 +00:00
gh-38464: Make tkinter nametowidget() work with cloned menus (GH-152336)
Map the auto-generated name of a cloned menu (a menu used as a menubar or a cascade) back to the original widget instead of raising KeyError. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
5fed5ce85d
commit
5c3555bdc5
3 changed files with 39 additions and 1 deletions
|
|
@ -390,6 +390,32 @@ def test_nametowidget(self):
|
|||
self.assertIs(self.root.nametowidget(str(b)), b)
|
||||
self.assertRaises(KeyError, self.root.nametowidget, '.nonexistent')
|
||||
|
||||
def test_nametowidget_menu_clone(self):
|
||||
# A menu used as a menubar or cascade is cloned by Tk under an
|
||||
# auto-generated name (each path component is the original name
|
||||
# prefixed with one or more '#' clone markers). nametowidget()
|
||||
# maps such a name back to the original widget (gh-38464).
|
||||
menubar = tkinter.Menu(self.root)
|
||||
filemenu = tkinter.Menu(menubar, tearoff=0)
|
||||
menubar.add_cascade(label='File', menu=filemenu)
|
||||
submenu = tkinter.Menu(filemenu, tearoff=0)
|
||||
filemenu.add_cascade(label='More', menu=submenu)
|
||||
self.root['menu'] = menubar
|
||||
self.root.update_idletasks()
|
||||
|
||||
originals = {menubar, filemenu, submenu}
|
||||
clones = []
|
||||
def collect(parent):
|
||||
for name in self.root.tk.splitlist(
|
||||
self.root.tk.call('winfo', 'children', parent)):
|
||||
clones.append(name)
|
||||
collect(name)
|
||||
collect('.')
|
||||
# Every menu (originals and clones) resolves to an original widget.
|
||||
self.assertTrue(any('#' in name for name in clones))
|
||||
for name in clones:
|
||||
self.assertIn(self.root.nametowidget(name), originals)
|
||||
|
||||
def test_focus_methods(self):
|
||||
f = tkinter.Frame(self.root, width=150, height=100)
|
||||
f.pack()
|
||||
|
|
|
|||
|
|
@ -1800,7 +1800,16 @@ def nametowidget(self, name):
|
|||
for n in name:
|
||||
if not n:
|
||||
break
|
||||
w = w.children[n]
|
||||
try:
|
||||
w = w.children[n]
|
||||
except KeyError:
|
||||
# Menu clones (a menu used as a menubar or a cascade) get
|
||||
# auto-generated names where each path component is the
|
||||
# original name prefixed with one or more '#' clone markers.
|
||||
# Map such a name back to the original widget.
|
||||
if not n.startswith('#'):
|
||||
raise
|
||||
w = w.children[n.rsplit('#', 1)[-1]]
|
||||
|
||||
return w
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
:meth:`!tkinter.Misc.nametowidget` now resolves the auto-generated names of
|
||||
cloned menus (a menu used as a menubar or a cascade) back to the original
|
||||
widget.
|
||||
Loading…
Add table
Add a link
Reference in a new issue