[Python / Tkinter]搜索Pandas DataFrame→创建一个简单的搜索表单以显示


简介

使用

DataFrame时,在某些情况下希望可以搜索并显示它。在创建GUI应用程序时特别有用。我想在下面搜索Pandas DataFrame并创建一个搜索表单以使用Tkinter进行显示。

样品

search.gif

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import pandas as pd
import tkinter as tk
import tkinter.ttk as ttk


class SearchWindow(tk.Frame):
    def __init__(self, master=None, parent=None):
        super().__init__(master)
        self.master = master
        self.master.geometry("300x300")
        self.master.title("検索ウインドウ")
        self.pack()
        self.set_data()
        self.create_widgets()

    def set_data(self):
        self.data = pd.read_csv("data.csv", encoding="utf-8")
        self.colname_list = ["食品コード", "食品名"]  # 検索結果に表示させる列名
        self.width_list = [100, 200]
        self.search_col = "検索キーワード"  # 検索キーワードの入力されている列名

    def create_widgets(self):
        self.pw_main = ttk.PanedWindow(self.master, orient="vertical")
        self.pw_main.pack(expand=True, fill=tk.BOTH, side="left")
        self.pw_top = ttk.PanedWindow(self.pw_main, orient="horizontal", height=25)
        self.pw_main.add(self.pw_top)
        self.pw_bottom = ttk.PanedWindow(self.pw_main, orient="vertical")
        self.pw_main.add(self.pw_bottom)
        self.creat_input_frame(self.pw_top)
        self.create_tree(self.pw_bottom)

    def creat_input_frame(self, parent):
        fm_input = ttk.Frame(parent, )
        parent.add(fm_input)
        lbl_keyword = ttk.Label(fm_input, text="キーワード", width=7)
        lbl_keyword.grid(row=1, column=1, padx=2, pady=2)
        self.keyword = tk.StringVar()
        ent_keyword = ttk.Entry(fm_input, justify="left", textvariable=self.keyword)
        ent_keyword.grid(row=1, column=2, padx=2, pady=2)
        ent_keyword.bind("<Return>", self.search)

    def create_tree(self, parent):
        self.result_text = tk.StringVar()
        lbl_result = ttk.Label(parent, textvariable=self.result_text)
        parent.add(lbl_result)
        self.tree = ttk.Treeview(parent)
        self.tree["column"] = self.colname_list
        self.tree["show"] = "headings"
        self.tree.bind("<Double-1>", self.onDuble)
        for i, (colname, width) in enumerate(zip(self.colname_list, self.width_list)):
            self.tree.heading(i, text=colname)
            self.tree.column(i, width=width)
        parent.add(self.tree)

    def search(self, event=None):
        keyword = self.keyword.get()
        result = self.data[self.data[self.search_col].str.contains(keyword, na=False)]
        self.update_tree_by_search_result(result)

    def update_tree_by_search_result(self, result):
        self.tree.delete(*self.tree.get_children())
        self.result_text.set(f"検索結果:{len(result)}")
        for _, row in result.iterrows():
            self.tree.insert("", "end", values=row[self.colname_list].to_list())

    def onDuble(self, event):
        for item in self.tree.selection():
            print(self.tree.item(item)["values"])


def main():
    root = tk.Tk()
    app = SearchWindow(master=root)
    app.mainloop()

if __name__ == "__main__":
    main()

读取的CSV的内容如下。 :

1
2
3
4
5
6
      食品コード              食品名                          検索キーワード
0      1001        アマランサス?玄穀                 アマランサス?玄穀 あまらんさす
1      1002           あわ?精白粒                        あわ?精白粒 あわ
2      1003          あわ?あわもち                  あわ?あわもち あわ あわもち
3      1004      えんばく?オートミール  えんばく?オートミール えんばく おーとみーる おーと おーつ
4      1005        大麦?七分つき押麦         大麦?七分つき押麦 おおむぎ ななぶつきおしむぎ

一点评论

输入文本→输入以在树中显示搜索结果。

链接了这些方法,以便可以通过按

Enter键来搜索它们。以下是部分:

1
        ent_keyword.bind("<Return>", self.search)

TTK的Treeview用作显示搜索结果的小部件。我喜欢它,因为它可以简单地以表格格式显示。执行search时,update_tree_by_search_result接收结果。在插入到Treeview中之前,将全部删除,然后添加。这部分是以下过程:

1
2
3
4
5
6
7
8
9
10
    def search(self, event=None):
        keyword = self.keyword.get()
        result = self.data[self.data[self.search_col].str.contains(keyword, na=False)]
        self.update_tree_by_search_result(result)

    def update_tree_by_search_result(self, result):
        self.tree.delete(*self.tree.get_children())
        self.result_text.set(f"検索結果:{len(result)}")
        for _, row in result.iterrows():
            self.tree.insert("", "end", values=row[self.colname_list].to_list())

尽管在GIF中未提及,但您也可以使用此搜索结果。用以下代码双击树项目时,onDouble被链接为过程。

1
        self.tree.bind("<Double-1>", self.onDuble)

onDouble如下。现在,您可以获取所选项目的值。

1
2
3
    def onDuble(self, event):
        for item in self.tree.selection():
            print(self.tree.item(item)["values"])