在树视图中手动更改值和列名称

时间:2018-04-19 07:46:50

标签: python tkinter

是否有任何方法可以通过单击要编辑的单元格来更改/删除/更新或在树视图中添加新值? 列名称的问题是相同的,我可以通过单击并在其上书写来手动更改列名吗?

这是我写的树视图代码:

from tkinter import *
from tkinter import ttk

myApp = Tk()
myApp.title("tree")                         
myApp.geometry("300x400")

tree = ttk.Treeview(myApp)
tree['show'] = 'headings'

sb = ttk.Scrollbar(myApp, orient="vertical", command=tree.yview)
sb.grid(row=1,column=12,rowspan=12,sticky="NS")

tree.configure(yscrollcommand=sb.set)

tree["columns"]=("1")

tree.column("1", width=230)
tree.heading("1", text="Name")

tree.insert("","end", values=("item"))

tree.grid(row=1 ,column=0,pady=5)

myApp.mainloop()

1 个答案:

答案 0 :(得分:1)

您希望实现的目标是什么,但您无法直接在Treeview单元格中写入文字,因此诀窍是使用place在您想要的单元格顶部显示Entry编辑。

所以这个想法如下:

  • 将鼠标点击Treeviewedit功能。
  • 在此功能中,使用tree.identify_region(x, y)标识点击所在的Treeview部分。
    • 如果这是一个单元格,您可以使用tree.identify_row(y)获取项目名称,使用tree.identify_column(x)获取该列,然后使用tree.bbox(item, column)函数获取Entry的位置和维度1}}。
    • 如果这是一个标题,则有点复杂,因为bbox仅适用于项目。我们仍然可以使用bbox获取列的x和宽度,但不能获得y和高度。因此,我们的想法是增加y,直到我们使用tree.identify_region(x, y)找到标题的边界来检查我们是否仍然在标题内(参见下面的代码)。
    • 如果“没有”,如果您在最后一项之下,则可以在最后一项下方显示Entry
  • Entry放在元素的顶部进行编辑
  • 当用户点击<Return>并销毁Entry
  • 时修改元素文字

以下是代码:

import tkinter as tk
from tkinter import ttk


def edit(event):

    if tree.identify_region(event.x, event.y) == 'cell':
        # the user clicked on a cell

        def ok(event):
            """Change item value."""
            tree.set(item, column, entry.get())
            entry.destroy()

        column = tree.identify_column(event.x)  # identify column
        item = tree.identify_row(event.y)  # identify item
        x, y, width, height = tree.bbox(item, column) 
        value = tree.set(item, column)

    elif tree.identify_region(event.x, event.y) == 'heading': 
        # the user clicked on a heading

        def ok(event):
            """Change heading text."""
            tree.heading(column, text=entry.get())
            entry.destroy()

        column = tree.identify_column(event.x) # identify column
        # tree.bbox work sonly with items so we have to get the bbox of the heading differently
        x, y, width, _ = tree.bbox(tree.get_children('')[0], column) # get x and width (same as the one of any cell in the column)
        # get vertical coordinates (y1, y2)
        y2 = y
        # get bottom coordinate
        while tree.identify_region(event.x, y2) != 'heading':  
            y2 -= 1
        # get top coordinate
        y1 = y2
        while tree.identify_region(event.x, y1) == 'heading':
            y1 -= 1
        height = y2 - y1
        y = y1
        value = tree.heading(column, 'text')

    elif tree.identify_region(event.x, event.y) == 'nothing': 
        column = tree.identify_column(event.x) # identify column
        # check whether we are below the last row:
        x, y, width, height = tree.bbox(tree.get_children('')[-1], column)
        if event.y > y:

            def ok(event):
                """Change item value."""
                # create item
                item = tree.insert("", "end", values=("", ""))
                tree.set(item, column, entry.get())
                entry.destroy()

            y += height
            value = ""
        else:
            return
    else:
        return
    # display the Entry   
    entry = ttk.Entry(tree)  # create edition entry
    entry.place(x=x, y=y, width=width, height=height,
                anchor='nw')  # display entry on top of cell
    entry.insert(0, value)  # put former value in entry
    entry.bind('<FocusOut>', lambda e: entry.destroy())  
    entry.bind('<Return>', ok)  # validate with Enter
    entry.focus_set()


myApp = tk.Tk()

tree = ttk.Treeview(myApp, show='headings', columns=("1", "2"))
tree['show'] = 'headings'

tree.column("1", width=230)
tree.heading("1", text="Name")
tree.column("2", width=230)
tree.heading("2", text="Price")
for i in range(10):
    item = tree.insert("", "end", values=("item %i" % i, i))
    tree.item(item, tags=item)
tree.bind('<1>', edit)

tree.pack(fill='both', expand=True)

myApp.mainloop()