Как сделать ТТК.Строки Treeview можно редактировать?
Есть ли способ использовать ttk Treeview с редактируемыми строками?
Я имею в виду, что он должен работать больше как таблица. Например, при двойном щелчке на элементе сделайте столбец #0 "редактируемым".
Если это невозможно, любой способ разрешить выбор мыши на элементе будет просто прекрасным. Я не нашел никаких упоминаний об этом в tkdoc или других документах.
4 ответов:
После долгих исследований я не нашел такой функции, поэтому я думаю, что она есть. 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 как самость._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'
Вы также можете открыть окно инструментов с редактируемыми полями, перечисленными с записями для обновления значений. Этот пример имеет treeview с тремя столбцами и не использует подклассы.
Привяжите двойной клик К этому:
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)
Я не знаю, как сделать строку редактируемой, но для захвата щелчка по строке вы используете виртуальное событие
<<TreeviewSelect>>. Это привязывается к подпрограмме с помощью методаbind(), затем вы используете методselection()для получения идентификаторов выбранных элементов.Это фрагменты из существующей программы, но они показывают основную последовательность вызовов:
# 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
Это просто для создания дерева для указанного пути, который задан в конструкторе. вы можете привязать свое событие к элементу в этом дереве. Функция события оставлена таким образом, что элемент может использоваться многими способами. В этом случае он будет показывать имя элемента при двойном щелчке по нему. Надеюсь, это кому-нибудь поможет.
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()
Comments