pythontkinterwidgetgridbind

How to use entry.bind("<FocusIn>", self.method_calling) for Entries made with grid/list


On this link is this code example that generates an entry grid in a Class with get(self) and set(set) method:

from tkinter import *


class Table:

    def __init__(self, root, values):

        total_rows = len(values)
        total_columns = len(values[0])

        # create a 2-D list to store the entry widgets
        self.entries = [[None]*total_columns for _ in range(total_rows)]

        # code for creating table
        for i in range(total_rows):
            for j in range(total_columns):
                e = Entry(root, width=10, fg='blue', font=('Arial',16,'bold'))
                e.grid(row=i, column=j)
                e.insert(END, values[i][j])
                self.entries[i][j] = e  # store entry into list

    # function to get value of entry at (row, col)
    def get(self, row, col):
        try:
            return self.entries[row][col].get()
        except IndexError as ex:
            print("Error on Table.get():", ex)

    # function to set value of entry at (row, col)
    def set(self, row, col, value):
        try:
            self.entries[row][col].delete(0, "end")
            self.entries[row][col].insert("end", value)
        except IndexError as ex:
            print("Error on Table.set():", ex)


# take the data
lst = [(1,'Raj','Mumbai',19),
       (2,'Aaryan','Pune',18),
       (3,'Vaishnavi','Mumbai',20),
       (4,'Rachna','Mumbai',21),
       (5,'Shubham','Delhi',21)]

# create root window
root = Tk()
root.geometry("800x600")

t = Table(root, lst) # pass lst to Table()

# update entry at row 0 column 1
t.set(0, 1, "hello")

root.mainloop()

Usually, for Entry placed "manually" I can use:

self.entry_path = Entry(root, width=72, font= ('Helvetica 13'))
self.entry_path.insert(INSERT, "Text Entry")
self.entry_path.bind("<FocusIn>", self.method_calling)

to call an event method to get:

def method_calling(self, event):
    self.entry_path.delete(0, END)
    self.entry_path.config(state= "disabled")

but I have no idea how I can .bind or .config Entry from a gird/list.

EDIT: If I am using like this:

class Table:

    def __init__(self, root, values):

        total_rows = len(values)
        total_columns = len(values[0])

        # create a 2-D list to store the entry widgets
        self.entries = [[None]*total_columns for _ in range(total_rows)]

        # code for creating table
        for i in range(total_rows):
            for j in range(total_columns):
                e = Entry(root, width=10, fg='blue', font=('Arial',16,'bold'))
                e.grid(row=i, column=j)
                e.bind("<FocusIn>", lambda: self.method_calling(i,j))
                e.insert(END, values[i][j])
                self.entries[i][j] = e  # store entry into list

    # function to get value of entry at (row, col)
    def get(self, row, col):
        try:
            return self.entries[row][col].get()
        except IndexError as ex:
            print("Error on Table.get():", ex)

    # function to set value of entry at (row, col)
    def set(self, row, col, value):
        try:
            self.entries[row][col].delete(0, "end")
            self.entries[row][col].insert("end", value)
        except IndexError as ex:
            print("Error on Table.set():", ex)

    def method_calling(self,event,i,j):
        print("row_"+str(i)+" column_"+str(j))


# take the data
lst = [(1,'Raj','Mumbai',19),
       (2,'Aaryan','Pune',18),
       (3,'Vaishnavi','Mumbai',20),
       (4,'Rachna','Mumbai',21),
       (5,'Shubham','Delhi',21)]

# create root window
root = Tk()
root.geometry("800x600")

t = Table(root, lst) # pass lst to Table()

# update entry at row 0 column 1
t.set(0, 1, "hello")

root.mainloop()

it gives me this error when I click on a cell:

enter image description here

and if I am using the code without "lambda:: in the command and without "event" in the calling methodl like this:

                e.grid(row=i, column=j)
                e.bind("<FocusIn>", self.method_calling(i,j))

.... ....

    def method_calling(self,i,j):
        print("row_"+str(i)+" column_"+str(j))

it automatically triggers without pressing anything.

enter image description here


Solution

  • You need to use default values of arguments to get the required row and column as below:

    e.bind("<FocusIn>", lambda evt, i=i, j=j: self.method_calling(i, j))
    

    And the definition of method_calling() should be:

    def method_calling(self, i, j):
        print(f"row_{i} column_{j}")