How to create a button or option which allows a user to filter a treeview based on a value in a column (python)?

不打扰是莪最后的温柔 提交于 2020-01-25 06:47:08

问题


I have created a GUI where volume data is being displayed based on a currency selection from a drop down menu. The displayed dataframe looks like the example below. The dataframe is displayed using a Treeview. I would like to create the option for the user to filter it down. To load the main frame the dropdown contains the main currency EUR in this example so when it is selected the volume for all the currency pairs against EUR is displayed. I would like to give the user the option to select a specific currency pair once the treeview is printed on the screen and filter the view down to it. I read about focusing on a tree but it seems to work for one row only rather then an entire block. What would be the best thing to use to achieve my goal?

from tkinter import *
import pandas as pd


class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid()
        self.master.title("Volume")

        for c in range(2, 7):
            self.master.rowconfigure(c, weight=1)

        for c in range(8):
            self.master.columnconfigure(c, weight=1)

        self.Frame1 = Frame(master, bg="blue")
        self.Frame1.grid(row=0, column=0, rowspan=1, columnspan=8, sticky=W + E + N + S)

        self.Frame2 = Frame(master, bg="lightblue")
        self.Frame2.grid(row=1, column=0, rowspan=1, columnspan=8, sticky=W + E + N + S)

        self.Frame3 = Frame(master, bg="white")
        self.Frame3.grid(row=2, column=0, rowspan=5, columnspan=8, sticky=W + E + N + S)

        self.Frame4 = Frame(master, bg="blue")
        self.Frame4.grid(row=7, column=0, rowspan=1, columnspan=8, sticky=W + E + N + S)

        label_title = Label(
            self.Frame1, text="Volume display", font=("Times New Roman", 30)
        )
        label_title.grid(row=0, column=1, padx=750)

        # drop down for currency
        label_option = Label(
            self.Frame2, text="Currency", font=("Times New Roman", 17, "bold")
        )
        label_option.grid(row=0, column=4)
        currencies = sorted(["USD", "GBP", "CAD", "EUR"])
        self.currency = StringVar(root)
        self.currency.set("EUR")
        option = OptionMenu(self.Frame2, self.currency, *currencies)
        option.grid(row=0, column=5)
        option["menu"].config(bg="white")
        option.config(font=("Times New Roman", 17), bg="white")

        # print df for currency
        self.Load_Df = Button(
            self.Frame4, text="Display Volume", command=self.load_data
        )
        self.Load_Df.config(font=("Times New Roman", 17), bg="white")
        self.Load_Df.grid(row=0, column=2, columnspan=2, ipadx=15)

        self.tree = ttk.Treeview(self.Frame3)

    def load_data(self):
        currency = self.currency.get()
        file_name = "D:/" + currency + "/volume.xlsx"
        final_df = pd.read_excel(file_name)

        self.clear_table()
        columns = list(final_df.columns)
        self.tree["columns"] = columns
        self.tree.pack(expand=TRUE, fill=BOTH)

        for i in columns:
            self.tree.column(i, anchor="w")
            self.tree.heading(i, text=i, anchor="w")

        for index, row in final_df.iterrows():
            self.tree.insert("", "end", text=index, values=list(row))

    def clear_table(self):
        for i in self.tree.get_children():
            self.tree.delete(i)


root = Tk()
app = Application(master=root)
app.mainloop()

回答1:


You can create a selection box for the user and display only the filtered results. Below is a sample utilizing ttk.Combobox base on your code:

from tkinter import *
import pandas as pd
from tkinter import ttk

df = pd.DataFrame({"Currency":["EUR","GBR","CAD","EUR"],
                   "Volumne":[100,200,300,400]})

class Application(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.title("Volume")

        self.tree = ttk.Treeview(self)
        columns = list(df.columns)
        self.combo = ttk.Combobox(self, values=list(df["Currency"].unique()),state="readonly")
        self.combo.pack()
        self.combo.bind("<<ComboboxSelected>>", self.select_currency)
        self.tree["columns"] = columns
        self.tree.pack(expand=TRUE, fill=BOTH)

        for i in columns:
            self.tree.column(i, anchor="w")
            self.tree.heading(i, text=i, anchor="w")

        for index, row in df.iterrows():
            self.tree.insert("", "end", text=index, values=list(row))

    def select_currency(self,event=None):
        self.tree.delete(*self.tree.get_children())
        for index, row in df.loc[df["Currency"].eq(self.combo.get())].iterrows():
            self.tree.insert("", "end", text=index, values=list(row))

root = Application()
root.mainloop()


来源:https://stackoverflow.com/questions/59644172/how-to-create-a-button-or-option-which-allows-a-user-to-filter-a-treeview-based

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!