-3

I've been trying to add a keyboard shortcut in Python 3 that activates a function.

from tkinter import *
from tkinter import messagebox
root = Tk()
def myThing():
    messagebox.showinfo("Hi", "Hello")
root.bind_all("<control-m>", myThing)
root.mainloop()

But when I press control m, this comes:

Error

sorry, the copy-paste doesn't work for the command prompt

But, when I do this:

from tkinter import *
from tkinter import messagebox
root = Tk()
def myThing(k):
    print(k)
root.bind_all("<Control-m>", myThing)
root.mainloop()

It does this:

enter image description here

what am I doing wrong?

I know that there are questions like this online, but I tried all of them, and got that error. I asked this question because the answers weren't clear enough for me.

PS: This is python 3.5.2

E.T.
  • 614
  • 6
  • 16

2 Answers2

1

When you bind an event to a function, tkinter will always pass in an object that represents the event. Most people name this argument event or evt:

def myThing(event):
    ...

This object has all sorts of useful information, such as a reference to the widget that caught the event, the x/y coordinate of the event, the key that was pressed (in the case of keyboard events) and so on.

If your function doesn't use this event, and you want to use this function both for bindings and for calling directly, you can make the event optional. Of course, if you do that you must make sure that the body of the function doesn't rely on the argument.

def myThing(event=None):
    ...

This is mentioned in the official python tkinter docs, and in just about every tutorial and documentation site related to tkinter. This is what the python docs say:

... func is a Python function, taking one argument, to be invoked when the event occurs. An Event instance will be passed as the argument. (Functions deployed this way are commonly known as callbacks.)

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
0

In your second example, you say print(k). The result is printing the tkinter.Event object. This means it works. However, in the second code snippet you have binded <Control-m> instead of <control-m>. Because <Control-m> seems to work, just capitalize the c in the first code snippet.

Read the error. the problem is that 1 argument was given to myThing(). However, in your first code snippet, you have defined myThing() as def myThing() instead of def myThing(k).

Reading and understanding errors in Python is a very valuable skill. If you know the types of errors Python gives, you can easily decipher what the problem is.

u8y7541
  • 548
  • 2
  • 8
  • 13
  • I tried that, but the same thing happened – E.T. Aug 26 '16 at 22:33
  • @Stiffy2000 I have fixed my answer :) – u8y7541 Aug 26 '16 at 22:36
  • I still want it to be used as `myThing()` and not `myThing(variable)` in short, I want to not have the `k` in there. I was just observing that the binding event returns something. I do not want it to do this, though. – E.T. Aug 26 '16 at 22:39
  • @Stiffy2000 You have to. Tkinter will always pass an event object to `myThing()`. Sometimes the data in the event object is useful, such as if a mouse click event is generated you could determine its coordinates. – u8y7541 Aug 26 '16 at 22:42
  • Is there a way to mute that? – E.T. Aug 26 '16 at 22:43
  • @Stiffy2000 Why do you need to mute it? There is no problem with it... I don't think there's a way but you can check the docs. – u8y7541 Aug 26 '16 at 22:44