How to bind an action to the heading of a tkinter treeview in python?
Asked Answered
D

3

9

I am using the tkinter Treeview widget to show a database. The command when clicking on one of the headings is used for sorting the table based on the clicked column.

Additionally I want a tooltip box show up as soon as I hover (or right click) over one of the headings. The tooltips aren't a problem for other widgets but the heading of a treeview isn't a full widget of course.

How can I bind any action to the headings except for the usual command?

Dorita answered 23/7, 2015 at 10:16 Comment(0)
B
11

You can bind the events to the treeview widget itself. The widget has a method named identify which can be used to determine which part of the treeview the event occurred over.

For example:

...
self.tree = ttk.Treeview(...)
self.tree.bind("<Double-1>", self.on_double_click)
...
def on_double_click(self, event):
    region = self.tree.identify("region", event.x, event.y)
    if region == "heading":
        ...
Brusa answered 23/7, 2015 at 14:19 Comment(1)
Thanks! I tried it with "tree.identify" which actually only returns if it's a cell or a a(ny) heading. I ended up using "tree.identify_column" which gives back a result like "#2" for the 3rd column, which is perfectly usable for me!Dorita
A
5

use -command in config:

def foo():
    pass

tree.heading(column1, text = 'some text', command = foo)
Aerophobia answered 19/12, 2016 at 3:4 Comment(1)
When assigning different commands to each heading in a loop, use lambda with the heading as argument: treeview.heading(col, command=lambda c=col: do_stuff(c)). This way, the reference to col is kept even outside the loop.Petrinapetrine
U
2

Use the tree.heading command as proposed by Mihail above, but note that if you are running from within a class, you'll need to pass a self into the method as usual.

Here is a Python 2 snippet that will load a treeview and demonstrate calling both a method and an external function:

import Tkinter
import ttk

class TreeWindow:
    def __init__(self):
        win = Tkinter.Tk()
        tree = ttk.Treeview(win,height=10,padding=3)

        self.tree = tree
        self.win = win

        self.tree["columns"] = ("Column 1","Column 2")
        self.tree.grid(row=1,column=0,sticky=Tkinter.NSEW)

        self.tree.column("Column 1", width=100)
        self.tree.heading("Column 1", text="Column 1", command=PrintColumnName1)

        self.tree.column("Column 2", width=100)
        self.tree.heading("Column 2", text="Column 2", command=self.PrintColumnName2)

        self.tree.insert('', 0, text="Row 1", values=("a",1))
        self.tree.insert('', 1, text="Row 2", values=("b",2))

        self.win.mainloop()

    def PrintColumnName2(self):
        print("Column 2")

def PrintColumnName1():
    print("Column 1")

treeWindow = TreeWindow()

Note for some reason, the first click doesn't seem to work immediately but gets stuck in the buffer until you click a second time - very eager to hear anyone with an explanation for this.

Untidy answered 11/4, 2018 at 19:48 Comment(1)
Doesn't happen for me in Windows 10. Maybe a bug that's since been fixed?Horacehoracio

© 2022 - 2024 — McMap. All rights reserved.