Как сделать ТТК.Строки Treeview редактируемые?
есть ли способ использовать ttk Treeview с редактируемыми строками?
Я имею в виду, что он должен работать больше как таблица. Например, при двойном щелчке по элементу сделайте столбец #0 "редактируемым".
Если это невозможно, любой способ разрешить выбор мыши на элементе будет просто прекрасным. Я не нашел упоминания об этом в tkdocs или других документах.
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.Дерево как само собой._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()