Search code examples
tkintermouseeventscrollable-table

How to get mouse click position as row, column in gridded tkinter frame?


This is my first SO question - I hope it makes sense. I have a scrollable, gridded tkinter frame which is populated by a table. The table has 10 columns of fixed width. The number of rows is variable, as is the height of each row. I want to be able to click on any particular row/column (of the grid) and be able to convey the row and column numbers back to the main program for further processing (eg, to drill down or to be able to update or delete that row). Data cells in the table are all tk.Text.

I can see how to find the x, y coordinates of a mouse click, but do not know how to translate that to row,column - especially as the frame (and hence table) is scrollable when the table is longer than the frame. I can't provide any code because I have no idea how to even start on this problem.

Sorry if this is a bit vague, but would appreciate any pointers from the experts. I am sure that this can't be a new requirement. I couldn't find any related answers on this site (getting row and column from mouse click event looked promising from the title, but this is actually the opposite - it gets the data in a cell at the clicked row/column). Maybe I was not asking the right question. Any advice would be appreciated.


Solution

  • It sounds like you are using grid to arrange text widgets. If that is the case, you can query the widget to find out the row and column it is in.

    Here's a simple example:

    import tkinter as tk
    
    widgets = {}
    root = tk.Tk()
    container = tk.Frame(root)
    container.pack(fill="both", expand=True)
    
    status = tk.Label(root, justify="left")
    status.pack(side="bottom", fill="x")
    
    def handle_click(event):
        grid_info = event.widget.grid_info()
        status.configure(text=f"row: {grid_info['row']:2} column: {grid_info['column']:2}")
    
    for row in range(10):
        for column in range(5):
            text = tk.Text(container, width=10, height=2, wrap="word")
            text.grid(row=row, column=column, sticky="nsew")
            text.bind("<1>", handle_click)
    
    tk.mainloop()
    

    screenshot