Reputation: 464
So my teacher told me to learn Tkinter be myself and I try to understand it. Here's is the program I'm looking at.
It asks for a name and last name. (Yeah, Spanish is my native language)
When I finish inserting the name, I just want to press enter to go to the next text box which is last name.
from tkinter import *
master = Tk()
Label(master, text="Ingrese sus nombres: ").grid(row=0)
Label(master, text="Ingrese sus apellidos: ").grid(row=1)
e1 = Entry(master)
e2 = Entry(master)
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
mainloop()
Upvotes: 6
Views: 8582
Reputation: 25
I 've found one solution about that.
if we have two entries like Entry_1 and Entry_2 then we want the cursor first stop in Entry_1 and when we press enter (or whatever we want other than "Return" key) the cursor will pass to the Entry_2.
entry_1.focus()
entry_1.bind("<Return>",lambda funct1:entry_2.focus())
Upvotes: 0
Reputation: 920
A quick and dirty way would be to bind
the first Entry
widget to a function that switches the focus to the other widget:
def go_to_next_entry(event):
e2.focus_set() # focus_set() switches the focus to the new widget
e1.bind('<Return>', go_to_next_entry)
# or, if you are familiar with lambdas, simply:
# e1.bind('<Return>', lambda e: e2.focus_set())
The .bind
method expects as a first argument a string representing the type of user interaction, and as a second argument, a function of a single argument (the event argument. In this case you do not have to care about that, but if you were monitoring the movement of the cursor, the event could give you its coordinates.)
For a more general way, things get trickier and this method seems more an hack than anything. Anyway, if you have many entries, you can automate the method like so:
Find all Entry
widgets. They are children of master
and you get them from master.winfo_children()
, which gives the children in the order they were declared in the code. Be careful, though, because you get all the children (the Labels
, too), so you have to filter the children (in this case the filter is "by type" and it is done with isinstance
):
entries = [child for child in master.winfo_children()
if isinstance(child, Entry)]
Then, you define the function that switches the focus to the desired widget:
def go_to_next_entry(event, entry_list, this_index):
next_index = (this_index + 1) % len(entry_list)
entry_list[next_index].focus_set()
The part next_index = (this_index + 1) % len(entries)
cycles over the entries (if you press Return at the last entry, you go to the first one).
Finally, you bind the switch function to each entry:
for idx, entry in enumerate(entries):
entry.bind('<Return>', lambda e, idx=idx: go_to_next_entry(e, entries, idx))
The scary part is: lambda e, idx=idx: go_to_next_entry(e, entries, idx)
. The important part here, is that lambda
is used to create another function (much like def
) that has 2 arguments instead of the 3 required by go_to_next_entry
. The idx=idx
part makes it possible to call the newly-created function with just 1 parameter (as required by .bind
.) To see why idx=idx
is actually important and could not be omitted, have a look at Generate Tkinter buttons dynamically (which is about buttons, but the principle is the same.)
The complete code:
from tkinter import *
master = Tk()
Label(master, text="Ingrese sus nombres: ").grid(row=0)
Label(master, text="Ingrese sus apellidos: ").grid(row=1)
e1 = Entry(master)
e2 = Entry(master)
e3 = Entry(master)
e4 = Entry(master)
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
e3.grid(row=2, column=1)
e4.grid(row=3, column=1)
def go_to_next_entry(event, entry_list, this_index):
next_index = (this_index + 1) % len(entry_list)
entry_list[next_index].focus_set()
entries = [child for child in master.winfo_children() if isinstance(child, Entry)]
for idx, entry in enumerate(entries):
entry.bind('<Return>', lambda e, idx=idx: go_to_next_entry(e, entries, idx))
mainloop()
Upvotes: 9