Home > Software design >  How to move in entries using the arrow keys by applying the bind and focus?
How to move in entries using the arrow keys by applying the bind and focus?

Time:04-06

I have some entries in tkinter. Currently, I need to move the cursor to each entry and click it to select it. I am looking to do this using the arrow keys. I saw we can use bind_class to select all the Entry widgets; however, I don't know how to work around focus() to move Up/Down/Left/Right in entries. here is my code:

import tkinter as tk


class Data:
    def __init__(self):
        self.x = tk.IntVar()


class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.minsize(700, 700)
        container = tk.Frame(self)
        container.pack()

        self.data = Data()

        self.frames = {}
        for F in (PageOne, ):
            frame = F(container, self.data)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()


class PageOne(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data

        self.row_list = []
        for i in range(4):
            self.entry_list = []
            for j in range(4):
                self.A = tk.Entry(self)
                self.A.grid(row=i, column=j)
                self.entry_list.append(self.A)
            self.row_list.append(self.entry_list)

        self.bind_class("Entry", "<Down>", self.next_widget)
        self.bind_class("Entry", "<Up>", self.next_widget)
        self.bind_class("Entry", "<Right>", self.next_widget)
        self.bind_class("Entry", "<Left>", self.next_widget)

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

app = SampleApp()
app.mainloop()

CodePudding user response:

You can use tk_focusPrev() and tk_focusNext() to get the required Entry for key Left and Right.

For key Up and Down, you can use grid_size() to get the number of columns and rows of grid and use grid_info() on Entry to get the grid information, i.e. row and column where the Entry is. Then determine which Entry should take the focus:

def next_widget(self, event):
    entry = event.widget
    if event.keysym in ('Up', 'Down'):
        cols, rows = entry.master.grid_size()
        info = entry.grid_info()
        if event.keysym == 'Up':
            row = (info['row'] if info['row'] > 0 else rows) - 1
        else:
            row = (info['row']   1) % rows
        self.row_list[row][info['column']].focus()
    elif event.keysym == 'Left':
        entry.tk_focusPrev().focus()
    elif event.keysym == 'Right':
        entry.tk_focusNext().focus()
    return "break"
  • Related