簡體   English   中英

在tkinter樹視圖中刪除帶有已識別“單元格”的行

[英]Delete row in tkinter treeview with identified “cell”

我用tkitner制作了一個樹狀視圖,它使您可以通過單擊按鈕在樹狀視圖中識別出一個“單元格”,我使用了tree.identify_region(event.x, event.y) == ' cell'

一鍵單擊即可識別“單元格”(我已使用bind功能<Button-1> )。 我想制作一個將刪除行(所選行)的函數,但是該函數不起作用。 它沒有顯示任何錯誤。 我認為問題在於,即使選擇了該行,也選擇了“單元格”。

我發布了完整的代碼(即使它很長),因為我認為您需要查看我為完成此操作所做的工作

這是代碼:

from tkinter import *
from tkinter import ttk
import math
from tkinter import messagebox

def edit(event):

    def double(event): # funkcija koja kreira celiju kada se klikne dupli klik
        try:        
            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 only 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>', ok)  #validate when you click on other cell
            entry.focus_set()

        except IndexError:

            Error=messagebox.showinfo("Error!","You have 0 rows. Please add a new row.")
            pass

    tree.bind('<Button-1>', double) #kreiranje celije za unos i novi red sa duplim klikom


    def deleterow(event):   # funkcija za brisanje izabranog reda sa delete i backspace dugmicima
        try:
            SelectedRow= tree.selection()[0]
            tree.delete(SelectedRow)

        except IndexError: 
            Error=messagebox.showinfo("Error!","Please seleect the project that you want to delete")
            sys.exit() #za resavalje greske
            pass

        except ValueError: 
            Error=messagebox.showinfo("Error!","Please seleect the project that you want to delete")
            sys.exit() #za resavalje greske
            pass

    tree.bind("<Delete>", deleterow)
    tree.bind("<BackSpace>", deleterow)

myApp = Tk()
myApp.title(" Program ")                         
myApp.geometry("1900x1000")

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

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

tree.configure(yscrollcommand=sb.set)

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

tree.column("1", width=50)
tree.column("2", width=50)

tree.heading("1", text="Project Name")
tree.heading("2", text="Size [m2]")


item = tree.insert("", "end", values=("",))
tree.item(item, tags=item)
tree.bind('<1>', edit)

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


myApp.mainloop()

如果我用<Double-Button-1>標識“單元格”,那么它就起作用了,因為單擊1只是識別行,而不是單元格。

如果我使用<Button-1>進行單元格識別,您有任何辦法嗎?

這有點困難,因為我對Treeview的經驗很少。 我試圖隔離不同的功能,並且還刪除了許多對於基本理解而言不必要的代碼。 我想我有一個可行的概念,但是我的代碼結構與您的代碼完全不同。 看看您的想法:

from tkinter import *
from tkinter import ttk

def cell(event):
    '''Identify cell from mouse position'''
    row, col = tree.identify_row(event.y), tree.identify_column(event.x)
    pos = tree.bbox(row, col)       # Calculate positon of entry
    return row, col, pos

def single(event=None):
    '''Single click to select row and column'''
    global row, col, pos
    row, col, pos = cell(event)
    print('Select', row, col)

def ok(event=None):
    '''Validate entry as at loses focus'''
    tree.set(*item, typed.get())    # Set tree cell text
    entry.place_forget()            # Remove entry without deleting it

def double(event=None):
    '''Double click to edit cell'''
    global row, col, pos, item
    row, col, pos = cell(event)
    print('Edit', row, col)
    item = row, col                 # Remember which item you are editing
    typed.set(tree.set(row, col))   # Set entry text
    x, y, w, h = pos                # Place entry on tree
    entry.place(x=x, y=y, width=w, height=h, anchor='nw')
    entry.focus_set()               # Set focus in entry

def deleterow(event):
    '''Delete selected row'''
    print('delete', len(tree.selection()))
    if len(tree.selection()) != 0:
        row = tree.selection()[0]
    try:
        print('deleterow', row)
        tree.delete(row)
    except:
        print('no row selected')


myApp = Tk()
myApp.title(" Program ")                         
myApp.geometry("600x600+800+50")

tree = ttk.Treeview(myApp, height=20)
tree['show'] = 'headings'
sb = ttk.Scrollbar(myApp, orient="vertical", command=tree.yview)
sb.grid(row=1,column=12,sticky="NS")
tree.configure(yscrollcommand=sb.set)
tree["columns"]=("1","2")
tree.column("1", width=150)
tree.column("2", width=150)
tree.grid(row=1 ,column=0,pady=5)

tree.heading("1", text="Project Name")
tree.heading("2", text="Size [m2]")

item = tree.insert("", "end", values=("Project Alice","500 GB"))
tree.item(item, tags=item)

# Mouse & keyboard bindings
tree.bind('<1>', single)
tree.bind('<Double-Button-1>', double)
tree.bind("<Delete>", deleterow)

# Create entry in global scope
typed = StringVar()
entry = ttk.Entry(tree, textvariable=typed)
entry.bind('<FocusOut>', ok)

myApp.mainloop()

我將控制台打印輸出保留在代碼中,因此更容易看到正在發生的情況。 我使用全局變量來跟蹤重要變量。 我對變量名的選擇可能會更好。

無論如何,使用此代碼,我可以選擇單個或雙擊任何行/列。 刪除行似乎工作正常。 我沒有添加新行的任何功能,但這應該不難。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM