python - tkinter treeview用法




如何使ttk.Treeview的行可編輯? (3)

有沒有辦法使用可編輯的行ttk樹視圖?

我的意思是它應該更像一張桌子。 例如,雙擊該項目,使#0列“可編輯”。

如果這是不可能的,任何允許在項目上選擇鼠標的方法都可以。 我在tkdocs或其他文件中沒有發現任何提及。


我不知道如何編輯行,但要捕獲點擊行,您可以使用<<TreeviewSelect>>虛擬事件。 這綁定到一個例程與bind()方法,然後您使用selection()方法來獲取所選項目的ID。

這些是來自現有程序的片段,但顯示調用的基本順序:

# in Treeview setup routine
    self.tview.tree.bind("<<TreeviewSelect>>", self.TableItemClick)

# in TableItemClick()
    selitems = self.tview.tree.selection()
    if selitems:
        selitem = selitems[0]
        text = self.tview.tree.item(selitem, "text") # get value in col #0

經過長時間的研究,我還沒有找到這樣的功能,所以我想有什麼。 Tk是非常簡單的界面,它允許程序員從基礎開始構建“高級”功能。 所以我希望這樣的行為。

def onDoubleClick(self, event):
    ''' Executed, when a row is double-clicked. Opens 
    read-only EntryPopup above the item's column, so it is possible
    to select text '''

    # close previous popups
    self.destroyPopups()

    # what row and column was clicked on
    rowid = self._tree.identify_row(event.y)
    column = self._tree.identify_column(event.x)

    # clicked row parent id
    parent = self._tree.parent(rowid)

    # do nothing if item is top-level        
    if parent == '':
        return

    # get column position info
    x,y,width,height = self._tree.bbox(rowid, column)

    # y-axis offset
    pady = height // 2

    # place Entry popup properly         
    url = self._tree.item(rowid, 'text')
    self.entryPopup = EntryPopup(self._tree, url)
    self.entryPopup.place( x=0, y=y+pady, anchor=W, relwidth=1)

這是在一個類中構建ttk.Treeview為self._tree的方法

而EntryPopup則是非常簡單的入門子類:

class EntryPopup(Entry):

    def __init__(self, parent, text, **kw):
        ''' If relwidth is set, then width is ignored '''
        super().__init__(parent, **kw)

        self.insert(0, text) 
        self['state'] = 'readonly'
        self['readonlybackground'] = 'white'
        self['selectbackground'] = '#1BA1E2'
        self['exportselection'] = False

        self.focus_force()
        self.bind("<Control-a>", self.selectAll)
        self.bind("<Escape>", lambda *ignore: self.destroy())

    def selectAll(self, *ignore):
        ''' Set selection on the whole text '''
        self.selection_range(0, 'end')

        # returns 'break' to interrupt default key-bindings
        return 'break'

您也可以彈出一個工具窗口,其中列出了用條目列出的可編輯字段來更新值。 這個例子有一個三列樹形視圖,不使用子類。

綁定你的雙擊這個:

def OnDoubleClick(self, treeView):
    # First check if a blank space was selected
    entryIndex = treeView.focus()
    if '' == entryIndex: return

    # Set up window
    win = Toplevel()
    win.title("Edit Entry")
    win.attributes("-toolwindow", True)

    ####
    # Set up the window's other attributes and geometry
    ####

    # Grab the entry's values
    for child in treeView.get_children():
        if child == entryIndex:
            values = treeView.item(child)["values"]
            break

    col1Lbl = Label(win, text = "Value 1: ")
    col1Ent = Entry(win)
    col1Ent.insert(0, values[0]) # Default is column 1's current value
    col1Lbl.grid(row = 0, column = 0)
    col1Ent.grid(row = 0, column = 1)

    col2Lbl = Label(win, text = "Value 2: ")
    col2Ent = Entry(win)
    col2Ent.insert(0, values[1]) # Default is column 2's current value
    col2Lbl.grid(row = 0, column = 2)
    col2Ent.grid(row = 0, column = 3)

    col3Lbl = Label(win, text = "Value 3: ")
    col3Ent = Entry(win)
    col3Ent.insert(0, values[2]) # Default is column 3's current value
    col3Lbl.grid(row = 0, column = 4)
    col3Ent.grid(row = 0, column = 5)

    def UpdateThenDestroy():
        if ConfirmEntry(treeView, col1Ent.get(), col2Ent.get(), col3Ent.get()):
            win.destroy()

    okButt = Button(win, text = "Ok")
    okButt.bind("<Button-1>", lambda e: UpdateThenDestroy())
    okButt.grid(row = 1, column = 4)

    canButt = Button(win, text = "Cancel")
    canButt.bind("<Button-1>", lambda c: win.destroy())
    canButt.grid(row = 1, column = 5)

然後確認更改:

def ConfirmEntry(self, treeView, entry1, entry2, entry3):
    ####
    # Whatever validation you need
    ####

    # Grab the current index in the tree
    currInd = treeView.index(treeView.focus())

    # Remove it from the tree
    DeleteCurrentEntry(treeView)

    # Put it back in with the upated values
    treeView.insert('', currInd, values = (entry1, entry2, entry3))

    return True

以下是刪除條目的方法:

def DeleteCurrentEntry(self, treeView):
    curr = treeView.focus()

    if '' == curr: return

    treeView.delete(curr)




ttk