Vittawat Laorungroj
Vittawat Laorungroj

Reputation: 99

search and select item in treeview tkinter python

I would like to create search_function to search data in treeview table. On my code, I do need to click search_button to select data in treeview table following my 3 request below.

from tkinter import *
from tkinter import ttk

GUI = Tk()
GUI.geometry('1920x1080')

tree_view_frame = Frame(GUI)
tree_view_frame.pack()
tree_scroll = Scrollbar(tree_view_frame)
tree_scroll.pack(side = RIGHT, fill = Y)
header = ['Part No.', 'Name', 'Unit', 'Quan', 'Price','Total', 'Initial Total']
hdsize = [60,240,60,60,70,80,80]
aanchor = [W,W,E,E,E,E,E]
global product_table
product_table = ttk.Treeview(tree_view_frame, columns = header, show = 'headings', height = 20, yscrollcommand=tree_scroll.set, selectmode="extended")
def treeview_sort_column(product_table, col, reverse):
    l = [(product_table.set(k, col), k) for k in product_table.get_children('')]
    l.sort(reverse=reverse)
    for index, (val, k) in enumerate(l):
        product_table.move(k, '', index)
    product_table.heading(col, command=lambda _col=col: treeview_sort_column(product_table, _col, not reverse))
for col in header:
    product_table.heading(col, text=col,command=lambda _col=col: treeview_sort_column(product_table, _col, False))
product_table.pack()
tree_scroll.config(command = product_table.yview)
for h,s,a in zip(header, hdsize, aanchor):
    product_table.heading(h, text = h)
    product_table.column(h,width = s, anchor = a)

Nameget = StringVar()
E_namme = ttk.Entry(GUI,textvariable = Nameget)
E_namme.pack()

def Add_Product(event = None):
    product_table.insert('', 'end', value = ('', Nameget.get()))
B_Add_product = ttk.Button(GUI, text = "Add Product", command = Add_Product)
B_Add_product.pack()

def search_function():
    query = Nameget.get()
    selections = []
    for child in product_table.get_children():
        if query in product_table.item(child)['values'][1]:
            selections.append(child)
            product_table.selection_set(selections[0])
            product_table.focus(selections[0])
    product_table.focus_force()
search_button = ttk.Button(GUI, text = "search_button", width = 15, command = search_function)
search_button.pack()

GUI.mainloop()
  1. for first click is to select the first result. enter image description here

  2. second or next click is to select the next result until last result and do it as loop. enter image description here

  3. auto scroll down the scrollbar to select the result when it not appear in the current page. enter image description here

In the current code, it can select only the first result and not auto scroll down the scrollbar.

Thank you in advance.

Upvotes: 0

Views: 1770

Answers (1)

David Meu
David Meu

Reputation: 1545

You can use see (ensures that item is visible) and loop over.

Any data structure can assist here use queue or dict like the example below:

(It is good to use some OOP)

from tkinter import *
from tkinter import ttk
from collections import defaultdict

GUI = Tk()
GUI.geometry("1920x1080")

tree_view_frame = Frame(GUI)
tree_view_frame.pack()
tree_scroll = Scrollbar(tree_view_frame)
tree_scroll.pack(side=RIGHT, fill=Y)
header = ["Part No.", "Name", "Unit", "Quan", "Price", "Total", "Initial Total"]
hdsize = [60, 240, 60, 60, 70, 80, 80]
aanchor = [W, W, E, E, E, E, E]
global product_table


class ProductMap:
    def __init__(self):
        self.selections = defaultdict(list)
        self.last_lookup = ""

    def treeview_sort_column(self, product_table, col, reverse):
        l = [(product_table.set(k, col), k) for k in product_table.get_children("")]
        l.sort(reverse=reverse)
        for index, (val, k) in enumerate(l):
            product_table.move(k, "", index)
        product_table.heading(
            col,
            command=lambda _col=col: product_map.treeview_sort_column(
                product_table, _col, not reverse
            ),
        )

    def search_function(self):
        query = Nameget.get()
        if not query:
            return
        children = product_table.get_children()
        for child in children:
            curr = product_table.item(child)["values"][1]
            if query in curr and child not in self.selections[query]:
                self.selections[query].append(child)
                product_table.selection_set(child)
                product_table.focus(child)
                product_table.see(child)
                self.last_lookup = query
                return
            elif query != self.last_lookup:
                self.selections = defaultdict(list)

    def Add_Product(self, event=None):
        product_table.insert("", "end", value=("", Nameget.get()))


product_map = ProductMap()

product_table = ttk.Treeview(
    tree_view_frame,
    columns=header,
    show="headings",
    height=20,
    yscrollcommand=tree_scroll.set,
    selectmode="extended",
)
for col in header:
    product_table.heading(
        col,
        text=col,
        command=lambda _col=col: product_map.treeview_sort_column(
            product_table, _col, False
        ),
    )
product_table.pack()
tree_scroll.config(command=product_table.yview)
for h, s, a in zip(header, hdsize, aanchor):
    product_table.heading(h, text=h)
    product_table.column(h, width=s, anchor=a)

Nameget = StringVar()
E_namme = ttk.Entry(GUI, textvariable=Nameget)
E_namme.pack()


B_Add_product = ttk.Button(GUI, text="Add Product", command=product_map.Add_Product)
B_Add_product.pack()


search_button = ttk.Button(
    GUI, text="search_button", width=15, command=product_map.search_function
)
search_button.pack()


GUI.mainloop()

Upvotes: 1

Related Questions