Search code examples
python-3.xtkintercallbackmenu

tkinter menu accelerator duplicating callbacks


I'm seeing some strange behavior running Python 3.7.6 and tkinter 8.6 on MacOS 10.14.6.

I've bound "Delete" to a function, and also added a menu command that triggers the same function. I've also added an accelerator option to the menu command, which only displays the text and doesn't actually create the shortcut (as noted here).

Except, in this case, it does seem to create a shortcut: pressing the "Delete" key triggers my function twice: once for the bound command, and a second time from the accelerator. Removing either the binding or the accelerator cause it to only trigger once; of course, removing both causes the keybind to no longer activate. It works fine when triggered from the menu, and this doesn't seem to happen with other keys or key combos.

I'm not sure whether I've missed a detail about Tkinter programming or I'm encountering a technical issue. I made sure to try a different keyboard, and am unsure whether it might be a bug with Tkinter on Mac.

The following code consistently exhibits my issue:

from tkinter import *

def bar(event=None):
    print("Called bar")

def foo(event=None):
    print("Called foo")

root = Tk()
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)


#works fine
filemenu.add_command(label="Something else", command=bar, accelerator="Control-s")
root.bind("<Control-s>", bar)

#triggers twice when using the "Del" key
filemenu.add_command(label="Delete a thing", command=foo, accelerator="Delete")
root.bind("<Delete>", foo)


menubar.add_cascade(label="File", menu=filemenu)
root.config(menu=menubar)
root.mainloop()

Triggering each shortcut once generates the following output:

Called bar
Called foo
Called foo

So this leaves me with two questions:

  1. Can this be replicated by other people?

  2. How might I resolve or work around it?


Solution

  • I also had this issue, and looking at the code it appears that it definitely does add bindings for your accelerators. In my app I worked around it by not binding the key presses on OSX but it's hardly ideal.. There is a Tk bug for this: https://core.tcl-lang.org/tk/tktedit?name=ead70921a9665f57d2fbcfb3cdee51391858bc96