style listas lista instalar crear python treeview tkinter ttk

python - listas - ¿Cómo hacer que las filas de ttk.Treeview sean editables?



tkinter ttk (4)

No sé si hacer que la fila sea editable, pero para capturar haciendo clic en una fila, usa el evento virtual <<TreeviewSelect>> . Esto se vincula a una rutina con el método bind() , luego utiliza el método selection() para obtener los identificadores de los elementos seleccionados.

Estos son fragmentos de un programa existente, pero muestran la secuencia básica de llamadas:

# 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

¿Hay alguna forma de usar ttk Treeview con filas editables?

Quiero decir que debería funcionar más como una mesa. Por ejemplo, al hacer doble clic en el elemento, la columna # 0 es ''editable''.

Si esto no es posible, cualquier forma de permitir la selección del mouse en el elemento estaría bien. No he encontrado ninguna mención de esto en tkdocs u otros documentos.


Después de una larga investigación, no encontré esa característica, así que supongo que hay alguna. Tk es una interfaz muy simple, que permite al programador crear funciones de "alto nivel" desde lo básico. Entonces mi comportamiento deseado de esta manera.

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)

Este es el método dentro de una clase que compone ttk.Treeview como self._tree

Y EntryPopup es entonces una subclase de entrada muy simple:

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''


Esto es solo para crear un árbol para la ruta especificada que se establece en el constructor. puedes vincular tu evento a tu elemento en ese árbol. La función de evento se deja de forma que el elemento se pueda usar de muchas maneras. En este caso, mostrará el nombre del artículo al hacer doble clic en él. Espero que esto ayude a alguien.

import ttk from Tkinter import* import os* class Tree(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent path = "/home/...." self.initUI(path) def initUI(self, path): self.parent.title("Tree") self.tree = ttk.Treeview(self.parent) self.tree.bind("<Double-1>", self.itemEvent) yScr = ttk.Scrollbar(self.tree, orient = "vertical", command = self.tree.yview) xScr = ttk.Scrollbar(self.tree, orient = "horizontal", command = self.tree.xview) self.tree.configure(yscroll = yScr.set, xScroll = xScr.set) self.tree.heading("#0", text = "My Tree", anchor = ''w'') yScr.pack(side = RIGHT, fill = Y) pathy = os.path.abspath(path) rootNode = self.tree.insert('''', ''end'', text = pathy, open = True) self.createTree(rootNode, pathy) self.tree.pack(side = LEFT, fill = BOTH, expand = 1, padx = 2, pady = 2) self.pack(fill= BOTH, expand = 1) def createTree(self, parent, path) for p in os.listdir(path) pathy = os.path.join(path, p) isdir = os.path.isdir(pathy) oid = self.tree.insert(parent, ''end'' text = p, open = False) if isdir: self.createTree(oid, pathy) def itemEvent(self, event): item = self.tree.selection()[0] # now you got the item on that tree print "you clicked on", self.tree.item(item,"text") def main(): root = Tk.Tk() app = Tree(root) root.mainloop() if __name__ == ''__main__'' main()


También puede abrir una ventana de herramienta con los campos editables listados con Entradas para actualizar los valores. Este ejemplo tiene una vista en árbol con tres columnas y no usa subclases.

Enlace su doble clic a esto:

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)

Luego confirme los cambios:

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

A continuación, le mostramos cómo eliminar una entrada:

def DeleteCurrentEntry(self, treeView): curr = treeView.focus() if '''' == curr: return treeView.delete(curr)