mirror of
https://github.com/python/cpython.git
synced 2026-06-28 11:50:50 +00:00
[3.13] gh-88758: Handle non-tkinter widgets in tkinter focus methods (GH-152337) (GH-152348)
focus_get(), focus_displayof(), focus_lastfor() and winfo_containing()
now return None instead of raising KeyError when the focused widget was
not created by tkinter (for example a torn-off menu).
(cherry picked from commit 5fed5ce85d)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7a835cbbfb
commit
cee72326ff
3 changed files with 36 additions and 4 deletions
|
|
@ -416,6 +416,22 @@ def test_focus_methods(self):
|
|||
self.root.update()
|
||||
self.assertIs(self.root.focus_get(), b)
|
||||
|
||||
def test_focus_methods_unresolvable(self):
|
||||
# The focus may be on a widget that tkinter did not create and so
|
||||
# cannot map to an instance (e.g. a torn-off menu). The focus
|
||||
# methods return None instead of raising KeyError (gh-88758).
|
||||
menu = tkinter.Menu(self.root, tearoff=1)
|
||||
menu.add_command(label='Hello')
|
||||
tearoff = self.root.tk.call('tk::TearOffMenu', str(menu), 0, 0)
|
||||
self.addCleanup(self.root.tk.call, 'destroy', tearoff)
|
||||
self.root.update()
|
||||
self.assertRaises(KeyError, self.root.nametowidget, tearoff)
|
||||
|
||||
self.root.tk.call('focus', '-force', tearoff)
|
||||
self.root.update()
|
||||
self.assertIsNone(self.root.focus_get())
|
||||
self.assertIsNone(self.root.focus_displayof())
|
||||
|
||||
def test_grab(self):
|
||||
f = tkinter.Frame(self.root)
|
||||
f.pack()
|
||||
|
|
|
|||
|
|
@ -803,7 +803,10 @@ def focus_get(self):
|
|||
the focus."""
|
||||
name = self.tk.call('focus')
|
||||
if name == 'none' or not name: return None
|
||||
return self._nametowidget(name)
|
||||
try:
|
||||
return self._nametowidget(name)
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def focus_displayof(self):
|
||||
"""Return the widget which has currently the focus on the
|
||||
|
|
@ -812,14 +815,20 @@ def focus_displayof(self):
|
|||
Return None if the application does not have the focus."""
|
||||
name = self.tk.call('focus', '-displayof', self._w)
|
||||
if name == 'none' or not name: return None
|
||||
return self._nametowidget(name)
|
||||
try:
|
||||
return self._nametowidget(name)
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def focus_lastfor(self):
|
||||
"""Return the widget which would have the focus if top level
|
||||
for this widget gets the focus from the window manager."""
|
||||
name = self.tk.call('focus', '-lastfor', self._w)
|
||||
if name == 'none' or not name: return None
|
||||
return self._nametowidget(name)
|
||||
try:
|
||||
return self._nametowidget(name)
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def tk_focusFollowsMouse(self):
|
||||
"""The widget under mouse will get automatically focus. Can not
|
||||
|
|
@ -1222,7 +1231,10 @@ def winfo_containing(self, rootX, rootY, displayof=0):
|
|||
+ self._displayof(displayof) + (rootX, rootY)
|
||||
name = self.tk.call(args)
|
||||
if not name: return None
|
||||
return self._nametowidget(name)
|
||||
try:
|
||||
return self._nametowidget(name)
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def winfo_depth(self):
|
||||
"""Return the number of bits per pixel."""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
:meth:`!tkinter.Misc.focus_get`, :meth:`!focus_displayof`,
|
||||
:meth:`!focus_lastfor` and :meth:`!winfo_containing` now return ``None``
|
||||
instead of raising :exc:`KeyError` when the widget was not created by
|
||||
:mod:`tkinter` (for example a torn-off menu).
|
||||
Loading…
Add table
Add a link
Reference in a new issue