简体   繁体   中英

Tkinter Bind Enter to Focus next Entry

I am trying to create a function that will bind enter to focus on the next entry field in the "insert' frame. Except, in the case of the last entry field, in which it will return the entered text in all the fields. I have tried using an iterator to get the next entry field to no avail. I am new to Python and to Tkinter. My main question revolves around the "getinsert" function, how can I focus on the next entry field? Is there some way to get the current focus and add 1 to it? Also, how do I check if the it is on the last field so i can cal the "getinsert" function?

Any help would be greatly appreciated

import tkinter as tk
from tkinter import messagebox

master = tk.Tk()

insertnames = ["Title", "Location", "Tags", "Section", "Blah"]
insertentries = {}
insertlabels = {}
main = tk.Frame(master)
insert = tk.Frame(master)
currentnames = iter(insertnames[0])

def mainmenu():
    main.pack()
    insertbutton.pack(fill = 'x')

def insertcall():
    main.forget()
    insert.pack()
    insertform()
    insertentries["Title"].bind('<Return>', insertfocus)
    insertentries["Location"].bind('<Return>', insertfocus)
    insertentries["Tags"].bind('<Return>', getinsert)

def getinsert(event):
    for entry in insertentries:
        print (insertentries[entry].get())
        insertentries[entry].delete(0, 'end')
    insert.forget()
    mainmenu()

def insertfocus(event):
    currentnames.next()
    insertentries[currentnames].focus()

def insertform():
    i = 0

    for name in insertnames:
        e = tk.Entry(insert)
        e.grid(row = i, column = 1)
        insertentries[name] = e

        lab = tk.Label(insert, text = name)
        lab.grid(row = i, column = 0)
        insertlabels[name] = lab

        i += 1

insertbutton = tk.Button(main, text = "Insert", command = insertcall)
mainmenu()

tk.mainloop()

I know it isn't the best option but a long-winded way to do it would be to hard-code it. Somebody with more experience with dictionaries might be able to do it in loops but I couldn't :)

import tkinter as tk

insertnames = ["Title", "Location", "Tags", "Section", "Blah"]
obj = []

root = tk.Tk()

firstFrame = tk.Frame(root)
entryFrame = tk.Frame(root)

def mainmenu():
    firstFrame.pack()
    insertButton.pack(fill='x')

def insertcall():
    firstFrame.forget()
    entryFrame.pack()

    title = tk.Entry(entryFrame)
    title.bind('<Return>', lambda event: focus(title))
    title.grid(row=0, column=1)
    obj.append(title)
    tk.Label(entryFrame, text='Title').grid(row=0, column=0)

    location = tk.Entry(entryFrame)
    location.bind('<Return>', lambda event: focus(location))
    location.grid(row=1, column=1)
    obj.append(location)
    tk.Label(entryFrame, text='Location').grid(row=1, column=0)

    tags = tk.Entry(entryFrame)
    tags.bind('<Return>', lambda event: focus(tags))
    tags.grid(row=2, column=1)
    obj.append(tags)
    tk.Label(entryFrame, text='Tags').grid(row=2, column=0)

    section = tk.Entry(entryFrame)
    section.bind('<Return>', lambda event: focus(section))
    section.grid(row=3, column=1)
    obj.append(section)
    tk.Label(entryFrame, text='Section').grid(row=3, column=0)

    blah = tk.Entry(entryFrame)
    blah.bind('<Return>', lambda event: focus(blah))
    blah.grid(row=4, column=1)
    obj.append(blah)
    tk.Label(entryFrame, text='Blah').grid(row=4, column=0)

def focus(entryobj):
    i = 0
    for item in obj: #for each try and get next item unless it gives an error (then it must be the last entry so put it to 0)
        try:
            if item == entryobj:
                obj[i+1].focus_set()
                break
        except IndexError:
            obj[0].focus_set()
        i += 1

insertButton = tk.Button(firstFrame, text='Insert', command=insertcall)
insertButton.pack()

mainmenu()

root.mainloop()

You are replicating the function of the tab key for moving between a set of widgets. This uses the virtual events <<NextWindow>> and <<PrevWindow>> . So the thing to do is have your <Return> handler generate this event. Then for the last entry you want to go to a specific widget. I've created an example that does this. You can either use something like this with a collection of widgets or you could arrange to inspect the widgets in the containing frame if you dig into what the tk_focusNext function is doing to work out the next widget to go to.

Edit : emulate the tk::TabToWindow function by generating the traversal events from python

import tkinter as tk

class MyEntry(tk.Entry):
    """Entry widget with Return bound to provide tabbing functionality"""
    def __init__(self, master, **kw):
        tk.Entry.__init__(self, master, **kw)
        self.next_widget = None
        self.bind("<Return>", self.on_ret)
    def on_ret(self, ev):
        if self.next_widget:
            self.event_generate('<<TraverseOut>>')
            self.next_widget.focus()
            self.next_widget.event_generate('<<TraverseIn>>')
        else:
            self.event_generate('<<NextWindow>>')
        return "break"
    def set_next(self, widget):
        """Override the default next widget for this instance"""
        self.next_widget = widget

def add_entry(parent, row, **kwargs):
    widget = MyEntry(parent, **kwargs)
    widget.grid(row=row, column=0, sticky=tk.NSEW)
    return widget

def main(args=None):
    root = tk.Tk()

    frame = tk.LabelFrame(root, text="Entries", width=200, height=200)

    entries = []
    for row in range(4):
        e = add_entry(frame, row)
        entries.append(e)
    e.set_next(entries[0])

    frame.grid_columnconfigure(0, weight=1)
    frame.grid_rowconfigure(0, weight=0)

    button = tk.Button(root, text="Exit", command=root.destroy)

    frame.grid(row=0, column=0, sticky=tk.NSEW)
    button.grid(row=1, column=0, sticky=tk.SE)
    root.grid_columnconfigure(0, weight=1)
    root.grid_rowconfigure(0, weight=1)

    entries[0].focus_set()
    root.mainloop()

if __name__ == '__main__':
    main()

You could bind the <Return> key for the Entry widgets in question to a function like this:

def entry_next(self, event):         
    event.widget.tk_focusNext().focus()
    return("break")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM