mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
[3.11] gh-75666: Tkinter: "unbind(sequence, funcid)" now only unbinds "funcid" (GH-111322) (GH-112801)
Previously, "widget.unbind(sequence, funcid)" destroyed the current binding
for "sequence", leaving "sequence" unbound, and deleted the "funcid"
command.
Now it removes only "funcid" from the binding for "sequence", keeping
other commands, and deletes the "funcid" command.
It leaves "sequence" unbound only if "funcid" was the last bound command.
(cherry picked from commit cc7e45cc57
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: GiovanniL <13402461+GiovaLomba@users.noreply.github.com>
This commit is contained in:
parent
8be7282f29
commit
010819a295
3 changed files with 52 additions and 12 deletions
|
@ -1448,10 +1448,24 @@ class Misc:
|
|||
return self._bind(('bind', self._w), sequence, func, add)
|
||||
|
||||
def unbind(self, sequence, funcid=None):
|
||||
"""Unbind for this widget for event SEQUENCE the
|
||||
function identified with FUNCID."""
|
||||
self.tk.call('bind', self._w, sequence, '')
|
||||
if funcid:
|
||||
"""Unbind for this widget the event SEQUENCE.
|
||||
|
||||
If FUNCID is given, only unbind the function identified with FUNCID
|
||||
and also delete the corresponding Tcl command.
|
||||
|
||||
Otherwise destroy the current binding for SEQUENCE, leaving SEQUENCE
|
||||
unbound.
|
||||
"""
|
||||
if funcid is None:
|
||||
self.tk.call('bind', self._w, sequence, '')
|
||||
else:
|
||||
lines = self.tk.call('bind', self._w, sequence).split('\n')
|
||||
prefix = f'if {{"[{funcid} '
|
||||
keep = '\n'.join(line for line in lines
|
||||
if not line.startswith(prefix))
|
||||
if not keep.strip():
|
||||
keep = ''
|
||||
self.tk.call('bind', self._w, sequence, keep)
|
||||
self.deletecommand(funcid)
|
||||
|
||||
def bind_all(self, sequence=None, func=None, add=None):
|
||||
|
|
|
@ -425,26 +425,46 @@ class BindTest(AbstractTkTest, unittest.TestCase):
|
|||
|
||||
def test_unbind2(self):
|
||||
f = self.frame
|
||||
f.wait_visibility()
|
||||
f.focus_force()
|
||||
f.update_idletasks()
|
||||
event = '<Control-Alt-Key-c>'
|
||||
self.assertEqual(f.bind(), ())
|
||||
self.assertEqual(f.bind(event), '')
|
||||
def test1(e): pass
|
||||
def test2(e): pass
|
||||
def test1(e): events.append('a')
|
||||
def test2(e): events.append('b')
|
||||
def test3(e): events.append('c')
|
||||
|
||||
funcid = f.bind(event, test1)
|
||||
funcid2 = f.bind(event, test2, add=True)
|
||||
|
||||
f.unbind(event, funcid)
|
||||
script = f.bind(event)
|
||||
self.assertNotIn(funcid, script)
|
||||
self.assertCommandNotExist(funcid)
|
||||
self.assertCommandExist(funcid2)
|
||||
funcid3 = f.bind(event, test3, add=True)
|
||||
events = []
|
||||
f.event_generate(event)
|
||||
self.assertEqual(events, ['a', 'b', 'c'])
|
||||
|
||||
f.unbind(event, funcid2)
|
||||
script = f.bind(event)
|
||||
self.assertNotIn(funcid2, script)
|
||||
self.assertIn(funcid, script)
|
||||
self.assertIn(funcid3, script)
|
||||
self.assertEqual(f.bind(), (event,))
|
||||
self.assertCommandNotExist(funcid2)
|
||||
self.assertCommandExist(funcid)
|
||||
self.assertCommandExist(funcid3)
|
||||
events = []
|
||||
f.event_generate(event)
|
||||
self.assertEqual(events, ['a', 'c'])
|
||||
|
||||
f.unbind(event, funcid)
|
||||
f.unbind(event, funcid3)
|
||||
self.assertEqual(f.bind(event), '')
|
||||
self.assertEqual(f.bind(), ())
|
||||
self.assertCommandNotExist(funcid)
|
||||
self.assertCommandNotExist(funcid2)
|
||||
self.assertCommandNotExist(funcid3)
|
||||
events = []
|
||||
f.event_generate(event)
|
||||
self.assertEqual(events, [])
|
||||
|
||||
# non-idempotent
|
||||
self.assertRaises(tkinter.TclError, f.unbind, event, funcid2)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
Fix the behavior of :mod:`tkinter` widget's ``unbind()`` method with two
|
||||
arguments. Previously, ``widget.unbind(sequence, funcid)`` destroyed the
|
||||
current binding for *sequence*, leaving *sequence* unbound, and deleted the
|
||||
*funcid* command. Now it removes only *funcid* from the binding for
|
||||
*sequence*, keeping other commands, and deletes the *funcid* command. It
|
||||
leaves *sequence* unbound only if *funcid* was the last bound command.
|
Loading…
Add table
Add a link
Reference in a new issue