Issue31485
Created on 2017-09-15 13:57 by j-4321-i, last changed 2022-04-11 14:58 by admin.
| Pull Requests | |||
|---|---|---|---|
| URL | Status | Linked | Edit |
| PR 17954 | closed | python-dev, 2020-01-11 21:30 | |
| Messages (10) | |||
|---|---|---|---|
| msg302256 - (view) | Author: Juliette Monsel (j-4321-i) * | Date: 2017-09-15 13:57 | |
I am using python 3.6.2 with tk 8.6.7 in Linux and when I call widget.unbind(<Sequence>, funcid), it unbinds all bindings for <Sequence>, while I would expect it to unbind only funcid. Here is an example reproducing the problem:
import tkinter as tk
root = tk.Tk()
def cmd1(event):
print('1')
def cmd2(event):
print('2')
def unbind1():
l.unbind('<Motion>', b1)
def unbind2():
l.unbind('<Motion>', b2)
l = tk.Label(root, text='Hover')
b1 = l.bind('<Motion>', cmd1)
b2 = l.bind('<Motion>', cmd2, True)
l.pack()
tk.Button(root, text='Unbind 1', command=unbind1).pack()
tk.Button(root, text='Unbind 2', command=unbind2).pack()
root.mainloop()
In this example, clicking on one of the buttons unbinds both bindings instead of only one.
|
|||
| msg302258 - (view) | Author: Juliette Monsel (j-4321-i) * | Date: 2017-09-15 14:37 | |
I have found a workaround to unbind a single binding (inspired by https://mail.python.org/pipermail/tkinter-discuss/2012-May/003151.html): def unbind(widget, seq, funcid): bindings = {x.split()[1][3:]: x for x in widget.bind(seq).splitlines() if x.strip()} try: del bindings[funcid] except KeyError: raise tk.TclError('Binding "%s" not defined.' % funcid) widget.bind(seq, '\n'.join(list(bindings.values()))) |
|||
| msg302262 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2017-09-15 16:21 | |
Tk do not provide a way of unbinding a specific command. It supports binding a script with replacing an existing binding, appending a script to an existing binding, and destroying an existing binding. Unbinding a specific command can be implemented in Python with a code similar to your example, but more complex due to taking to account different corner cases. Do you want to write a patch and open a pull request Juliette? |
|||
| msg302293 - (view) | Author: Terry J. Reedy (terry.reedy) * ![]() |
Date: 2017-09-15 19:47 | |
The unbind docstring, "Unbind for this widget for event SEQUENCE the
function identified with FUNCID" implies to me the behavior Juliette expected. The NMT reference unpacks this to two sentences. Reading the code
self.tk.call('bind', self._w, sequence, '')
if funcid:
self.deletecommand(funcid)
the docstring should be something like "Unbind for this widget the event SEQUENCE. If funcid is given, delete the command also" This part of the bind docstring, "Bind will return an identifier to allow deletion of the bound function with unbind without memory leak." implies that the unbind behavior is deliberate.
Serhiy, are you proposing to add a new method that does what some people thought unbind would do?
|
|||
| msg302299 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2017-09-15 20:49 | |
I don't think a new method is needed. We can make unbind() destroying all bindings if FUNCID is not given (note that registered commands are leaked in this case), and only the specified command if it is specified. We can add a boolean parameter (similar to the one in bind()) for restoring the old behavior if this is needed. |
|||
| msg302487 - (view) | Author: Juliette Monsel (j-4321-i) * | Date: 2017-09-18 20:35 | |
I don't mind writing a patch and opening a pull request, however I don't know which corner cases I need to take into account. |
|||
| msg358227 - (view) | Author: Giovanni Lombardo (glombardo) * | Date: 2019-12-10 21:28 | |
http://docs.python.org/devguide/triaging.html#assigned-to |
|||
| msg359369 - (view) | Author: Giovanni Lombardo (glombardo) * | Date: 2020-01-05 18:22 | |
I propose the below fix:
```
def unbind(self, sequence, funcid=None):
"""Unbind for this widget for event SEQUENCE the
function identified with FUNCID."""
bound = ''
if funcid:
self.deletecommand(funcid)
funcs = self.tk.call('bind', self._w, sequence, None).split('\n')
bound = '\n'.join([f for f in funcs if not f.startswith('if {{"[{0}'.format(funcid))])
self.tk.call('bind', self._w, sequence, bound)
```
|
|||
| msg360142 - (view) | Author: Terry J. Reedy (terry.reedy) * ![]() |
Date: 2020-01-16 20:47 | |
Serhiy, if I understand your last message (msg302299), the docstring should read: Unbind for this widget the event SEQUENCE. If FUNCID is given, only unbind the function identified with FUNCID and also delete that command. The main doc change is to specify what happens when funcid is not given while the code change in the patch is to no longer unbind everything when funcid *is* given. |
|||
| msg360145 - (view) | Author: Terry J. Reedy (terry.reedy) * ![]() |
Date: 2020-01-16 21:37 | |
Serhiy, given that the code did not match the docstring and that we are changing the code to match the clarified docstring, should we consider this a bugfix, and, should we backport it? |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022-04-11 14:58:52 | admin | set | github: 75666 |
| 2020-05-26 07:51:27 | terry.reedy | set | versions: + Python 3.10, - Python 3.7 |
| 2020-01-16 21:37:07 | terry.reedy | set | messages: + msg360145 |
| 2020-01-16 20:47:31 | terry.reedy | set | messages: + msg360142 |
| 2020-01-11 21:30:44 | python-dev | set | keywords:
+ patch stage: patch review pull_requests: + pull_request17364 |
| 2020-01-05 18:22:42 | glombardo | set | messages: + msg359369 |
| 2019-12-10 21:28:55 | glombardo | set | nosy:
+ glombardo messages: + msg358227 |
| 2017-09-18 20:35:37 | j-4321-i | set | messages: + msg302487 |
| 2017-09-15 20:49:28 | serhiy.storchaka | set | messages: + msg302299 |
| 2017-09-15 19:47:57 | terry.reedy | set | versions:
+ Python 3.7, - Python 3.6 nosy: + terry.reedy messages: + msg302293 type: behavior -> enhancement |
| 2017-09-15 16:21:41 | serhiy.storchaka | set | nosy:
+ serhiy.storchaka messages: + msg302262 |
| 2017-09-15 14:37:29 | j-4321-i | set | messages: + msg302258 |
| 2017-09-15 13:57:14 | j-4321-i | create | |
