在 tkinter 的树视图中选择多行并同时获取它们

Posted

技术标签:

【中文标题】在 tkinter 的树视图中选择多行并同时获取它们【英文标题】:Selecting multiple rows and fetching them simultaneously in treeview in tkinter 【发布时间】:2021-07-16 01:46:03 【问题描述】:

如何在树视图中选择多行,在树视图中从 mysql 数据库中提取数据,以便我可以在我的文本框中显示它们。我可以一次为一行执行此操作,但不确定如何选择多个条目。我的 GUI 中基本上有 2 个框架,左右框架。左框架显示带有动物名称的树视图,右框架显示文本框。当有人选择动物名称并点击 Add 按钮时,它应该被添加到右侧的文本框中。只是想弄清楚如何为多项选择执行此操作。以下是我目前的代码。

from tkinter import *
from tkinter import ttk
import pymysql


class Animals_App:
    def __init__(self, root):
        self.root = root
        self.root.title("Animals")
        self.root.geometry("1350x750+0+0")
        self.root.resizable(FALSE, FALSE)
        title = Label(self.root, text="Animals", font=("times new roman", 30, "bold"), bg="#262626",
                      fg="white").place(x=0, y=0, relwidth=1)
        self.root.config(background="powder blue")

        # =====Variables========


        self.animal_var = StringVar()

        # ==For displaying added Animal names on the right text box
        def display_name():
            txt_box.insert(END, 'Animal : ' + self.animal_var.get() + '\n')

        # ==========Frame 1 (Left Frame)===========
        Top_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
        Top_Frame.place(x=10, y=50, width=750, height=620)
        Addbtn = Button(Top_Frame, padx=16, pady=1, bd=7, fg='black', font=('arial', 16, 'bold'), width=4,
        text='Add', bg='powder blue', command=display_name).grid(row=0, column=0)

        Table_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
        Table_Frame.place(x=10, y=130, width=750, height=620)

        scroll_x = Scrollbar(Table_Frame, orient=HORIZONTAL)
        scroll_y = Scrollbar(Table_Frame, orient=VERTICAL)

        self.Animals_table = ttk.Treeview(Table_Frame,
                                          columns=("animal"),
                                          xscrollcommand=scroll_x.set, yscrollcommand=scroll_y.set)
        scroll_x.pack(side=BOTTOM, fill=X)
        scroll_y.pack(side=RIGHT, fill=Y)
        scroll_x.config(command=self.Animals_table.xview)
        scroll_y.config(command=self.Animals_table.yview)

        self.Animals_table.heading("animal", text="Animal Names")
        self.Animals_table['show'] = 'headings'

        self.Animals_table.column("animal", width=100)

        self.Animals_table.pack(fill=BOTH, expand=1)

        self.Animals_table.bind("<ButtonRelease-1>", self.get_cursor)
        self.fetch_data()

        # ==========Frame 2 (Right Frame)===========
        Txt_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
        Txt_Frame.place(x=770, y=70, width=580, height=620)

        scroll_y = Scrollbar(Txt_Frame, orient=VERTICAL)
        scroll_y.pack(fill=Y, side=RIGHT)

        txt_box = Text(Txt_Frame, font=("times new roman", 15), bg="lightyellow", fg="black",
                       yscrollcommand=scroll_y.set)
        txt_box.pack(fill=BOTH, expand=1)
        scroll_y.config(command=txt_box.yview)

        # txt_box.insert(END, 'Animal : ' + '\n')

    def fetch_data(self):
        con = pymysql.connect(host="localhost", user="root", password="", database="animaltree")
        cur = con.cursor()
        cur.execute("select * from animals")
        rows = cur.fetchall()
        # rows=["Cow","Deer","Dog","Zebra"]
        if len(rows) != 0:
            self.Animals_table.delete(*self.Animals_table.get_children())
            for row in rows:
                self.Animals_table.insert('', END, values=row)
            con.commit()
        con.close()

    def get_cursor(self, ev):
        cursor_row = self.Animals_table.focus()
        contents = self.Animals_table.item(cursor_row)
        row = contents['values']
        self.animal_var.set(row[0])


root = Tk()
obj = Animals_App(root)
root.mainloop()

【问题讨论】:

您的意思是要从树形视图中选择多个项目? @CoolCloud 是的,没错。 使用selectmode='multiple' ?作为树视图的一个选项。 Treeview的默认选择方式已经是多重。您需要使用.selection() 而不是.focus() 来获取所选项目。 @acw1668 感谢您的回答。另一个问题,在这种情况下存储多个变量的最佳方法是什么。对于单选,这就是我正在做的事情:self.animal_var.set(row[0]) 【参考方案1】:

Treeview的默认选择模式已经是多重模式。您需要使用.selection() 而不是.focus() 来获取所选项目。

为了保存选择,将self.animal_varStringVar()更改为Variable()并更新display_name()self.get_cursor()如下:

class Animals_App:
    def __init__(self, root):
        ...
        self.animal_var = Variable()  # changed from StringVar()

        def display_name():
            txt_box.insert(END, 'Animal : ' + ', '.join(self.animal_var.get()) + '\n')

        ...

    def get_cursor(self, ev):
        self.animal_var.set([ev.widget.item(idx)['values'][0] for idx in ev.widget.selection()])

【讨论】:

以上是关于在 tkinter 的树视图中选择多行并同时获取它们的主要内容,如果未能解决你的问题,请参考以下文章

在tkinter的treeview中的for循环中的每个父节点下添加子节点

Visual Studio Code:如何删除 html 标签并同时写入多行?

在尝试搜索数据库中的名称时遇到Tkinter Treeview和SQLite的问题

在python tkinter中为事件创建日历视图[关闭]

Python,Tkinter:如何在可滚动画布上获取坐标

更改 Tkinter 列表框选择时获取回调?