10

I am trying to bind the Enter key with a button.

In the bellow code, I am trying to get entries from the entry widget, when the button bt is pressed, it calls theenter() method which gets the entries.

I also want it to be called by pressing the Enter key, I am not getting the desired results.

The values entered in the entry widget is not being read and the enter method is called and just an empty space is inserted in my Database

Help me figure out my problem, thank you!

from tkinter import *
import sqlite3

conx = sqlite3.connect("database_word.db")

def count_index():
    cur = conx.cursor()
    count = cur.execute("select count(word) from words;")
    rowcount = cur.fetchone()[0]
    return rowcount

def enter():  #The method that I am calling from the Button
    x=e1.get()
    y=e2.get()
    ci=count_index()+1
    conx.execute("insert into words(id, word, meaning) values(?,?,?);",(ci,x,y))
    conx.commit()

fr =Frame()  #Main
bt=Button(fr)  #Button declaration
fr.pack(expand=YES)
l1=Label(fr, text="Enter word").grid(row=1,column=1)
l2=Label(fr, text="Enter meaning").grid(row=2,column=1)
e1=Entry(fr)
e2=Entry(fr)
e1.grid(row=1,column=2)
e2.grid(row=2,column=2)
e1.focus()
e2.focus()
bt.config(text="ENTER",command=enter)
bt.grid(row=3,column=2)
bt.bind('<Return>',enter)   #Using bind

fr.mainloop()
Rahul
  • 230
  • 1
  • 3
  • 15
  • 3
    Just like button `command`, bind also takes the reference of a function rather than calling the function itself. Change `enter()` with `enter` in`bt.bind`. – Nae Nov 24 '17 at 15:02
  • 4
    In addition to Nae's comment, I think you want to bind `` to the entries, not the button which does not have keyboard focus. – j_4321 Nov 24 '17 at 15:06
  • I tried using bind to entry too. Didn't work, and also tried focusing after focusing it on the button by pressing even that didn't work. – Rahul Nov 24 '17 at 15:10
  • By did not work, do you mean that there was an error or that it just did not do what you expected? – j_4321 Nov 24 '17 at 15:15
  • No error was shown, just a **NULL** was inserted into my database, that means, the method worked fine but it couldn't get the value from the entry or It was called before the entry was made. I also have to say that, the program works as intended if clicked on the button. – Rahul Nov 24 '17 at 15:20
  • Related: [How do I bind the enter key to a function in tkinter?](https://stackoverflow.com/q/16996432/3357935) – Stevoisiak Feb 22 '18 at 15:07

2 Answers2

15

2 things:

You need to modify your function to accept the argument that bind passes. (You don't need to use it, but you need to accept it).

def enter(event=None):

And you need to pass the function, not the result, to the bind method. So drop the ().

bt.bind('<Return>',enter)

Note this binds Return to the Button, so if something else has focus then this won't work. You probably want to bind this to the Frame.

fr.bind('<Return>',enter)

If you want a way to push an in focus Button the space bar already does that.

Novel
  • 13,406
  • 2
  • 25
  • 41
  • I tried removing the (), It still doesn't work. pls help. – Rahul Nov 24 '17 at 16:14
  • @Rahul did you do the first thing I mentioned and add `event=None` to the function definition? – Novel Nov 24 '17 at 16:50
  • 1
    @Rahul "It still doesn't work" does not tell me much. *What* does not work? What errors do you get? – Novel Nov 24 '17 at 16:51
  • Oh wow! it worked. I didn't add event=None in the method defenition. That was the problem. – Rahul Nov 24 '17 at 17:32
  • 1
    This was the problem before- No error was shown, just a NULL was inserted into my database, that means, the method worked fine but it couldn't get the value from the entry or It was called before the entry was made. I also have to say that, the program works as intended if clicked on the button. – Rahul Nov 24 '17 at 17:34
  • @Rahul your python code would have thrown a TypeError if you left off the `event=None`. If you can't see the errors that your code throws then you need to run it differently. – Novel Nov 24 '17 at 17:39
  • I changed what you told to and it worked as intended. The values where correctly taken and entered into the database – Rahul Nov 24 '17 at 17:46
11

In the question and in Novel's answer, first, the button is bound to the enter function using bt.config(text="ENTER",command=enter). After that, the function is bound to the enter/return key, but in fact, the button and the enter/return key are still quite independent.

In the case of this question, I assume that this is not really a problem, but if you often want to change the button's command, it may be boring to also have to change the binding to the enter/return key every time.

So you may think: is there a way to give the enter key automatically the same command as the button?

Yes, there is!

The Tkinter Button has the invoke() method, which calls the button's command and returns the command's return value:

import tkinter as TK

def func():
    print('the function is called!')

root = TK.Tk()
button= TK.Button(root, text='call the function', command=func) # not func()!
button.pack()
button.invoke() # output: 'the function is called!'
root.mainloop()

We can simply bind this method to the enter key:

root.bind('<Return>', button.invoke) # again without '()'!

But wait, this gives the same problem as before: the button.invoke() method doesn't accept the event argument from the binding, but we can't (easily) change that method. The solution for that is using a lambda:

root.bind('<Return>', lambda event=None: button.invoke()) # This time *with* '()'!!!

To be complete, I will give an example below:

import tkinter as TK

root = TK.Tk()
button= TK.Button(root)
button.pack()

def func1():
    print('func1 is called!')
    button.config(text='call func2', command=func2)
def func2():
    print('func2 is called!')

button.config(text='call func1', command=func1)

root.bind('<Return>', lambda event=None: button.invoke())
root.mainloop()

Explanation:

  • When you press enter or click the button the first time, 'func1 is called!' will be printed.
  • When you press enter or click the button the second time, 'func2 is called!' will be printed. The enter key should do the same as the button, although the key's binding is not changed.
cbjeukendrup
  • 3,216
  • 2
  • 12
  • 28