Python 如何制作ttk.Treeview';哪些行是可编辑的?
有没有办法将ttk Treeview与可编辑行一起使用 我的意思是它应该更像一张桌子。例如,双击项目,使#0列“可编辑”Python 如何制作ttk.Treeview';哪些行是可编辑的?,python,treeview,tkinter,ttk,Python,Treeview,Tkinter,Ttk,有没有办法将ttk Treeview与可编辑行一起使用 我的意思是它应该更像一张桌子。例如,双击项目,使#0列“可编辑” 如果这是不可能的,任何允许鼠标在项目上选择的方法都可以。我在tkdocs或其他文档中没有发现任何关于这一点的内容。我不知道如何使行可编辑,但要捕获单击行的行为,可以使用虚拟事件。使用bind()方法将其绑定到例程,然后使用selection()方法获取所选项目的ID 这些是来自现有程序的片段,但显示了基本的调用顺序: # in Treeview setup routine
如果这是不可能的,任何允许鼠标在项目上选择的方法都可以。我在tkdocs或其他文档中没有发现任何关于这一点的内容。我不知道如何使行可编辑,但要捕获单击行的行为,可以使用
虚拟事件。使用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
树视图设置例程中的#
self.tview.tree.bind(“,self.TableItemClick)
#在TableItemClick()中
selitems=self.tview.tree.selection()
如果选择下列项目:
selitem=selitems[0]
text=self.tview.tree.item(selitem,“text”)#获取列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)
# get column position info
x,y,width,height = self._tree.bbox(rowid, column)
# y-axis offset
# pady = height // 2
pady = 0
# place Entry popup properly
text = self._tree.item(rowid, 'text')
self.entryPopup = EntryPopup(self._tree, rowid, text)
self.entryPopup.place( x=0, y=y+pady, anchor=W, relwidth=1)
这是一个类中的方法,该类将ttk.Treeview组成self.\u树
EntryPopup是非常简单的条目子类:
class EntryPopup(Entry):
def __init__(self, parent, iid, text, **kw):
''' If relwidth is set, then width is ignored '''
super().__init__(parent, **kw)
self.tv = parent
self.iid = iid
self.insert(0, text)
# self['state'] = 'readonly'
# self['readonlybackground'] = 'white'
# self['selectbackground'] = '#1BA1E2'
self['exportselection'] = False
self.focus_force()
self.bind("<Return>", self.on_return)
self.bind("<Control-a>", self.select_all)
self.bind("<Escape>", lambda *ignore: self.destroy())
def on_return(self, event):
self.tv.item(self.iid, text=self.get())
self.destroy()
def select_all(self, *ignore):
''' Set selection on the whole text '''
self.selection_range(0, 'end')
# returns 'break' to interrupt default key-bindings
return 'break'
class EntryPopup(条目):
定义初始值(自身、父项、iid、文本,**kw):
''如果设置了relwidth,则忽略宽度''
超级()
self.tv=家长
self.iid=iid
self.insert(0,文本)
#self['state']='readonly'
#自我['readonlybackground']='white'
#self['selectbackground']='1BA1E2'
self['exportselection']=False
self.focus_force()
self.bind(“,self.on_return”)
self.bind(“,self.select\u all)
self.bind(“,lambda*忽略:self.destroy())
返回时的def(自身、事件):
self.tv.item(self.iid,text=self.get())
自我毁灭
def全选(自选,*忽略):
''在整个文本上设置选择''
自选择范围(0,“结束”)
#返回“break”以中断默认键绑定
返回“中断”
这仅用于为构造函数中设置的指定路径创建树。您可以将事件绑定到该树上的项目。事件函数以一种可以以多种方式使用该项的方式保留。在本例中,当双击项目时,它将显示该项目的名称。希望这对别人有帮助
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()
导入ttk
从Tkinter进口*
导入操作系统*
类树(框架):
定义初始化(自身,父级):
帧。\uuuu初始化(自,父)
self.parent=parent
path=“/home/…”
self.initUI(路径)
def初始用户界面(自身,路径):
self.parent.title(“树”)
self.tree=ttk.Treeview(self.parent)
self.tree.bind(“,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=“我的树”,anchor='w')
yScr包装(侧面=右侧,填充=Y)
path=os.path.abspath(路径)
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(填充=两者,扩展=1)
def createTree(自、父、路径)
对于os.listdir(路径)中的p
path=os.path.join(路径,p)
isdir=os.path.isdir(pathy)
oid=self.tree.insert(父级,'end'text=p,open=False)
如果是isdir:
self.createTree(oid,pathy)
def itemEvent(自身,事件):
item=self.tree.selection()[0]#现在您在该树上获得了该项
打印“你点击的”,self.tree.item(item,“text”)
def main():
root=Tk.Tk()
app=树(根)
root.mainloop()
如果uuuu name uuuuu=='\uuuuuuu main\uuuuuu'
main()
您还可以弹出一个工具窗口,其中列出了可编辑字段,其中包含用于更新值的条目。这个例子有一个三列的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 DeleteCurrentEntry(self, treeView):
curr = treeView.focus()
if '' == curr: return
treeView.delete(curr)
从tkinter导入ttk
从tkinter进口*
root=Tk()
列=(“项”、“值”)
Treeview=ttk.Treeview(根,高度=18,show=“headers”,columns=columns)#
Treeview.column(“项目”,宽度=200,锚点='center')
列(“值”,宽度=200,锚点=”中心“)
Treeview.heading(“Items”,text=“Items”)
Treeview.heading(“值”,text=“值”)
Treeview.pack(侧边=左侧,填充=两侧)
名称=['Item1','Item2','Item3']
ipcode=['10','25','163']
对于范围内的i(最小值(len(名称),len(ipcode)):
insert(“”,i,value=(名称[i],ipcode[i]))
def treeview_sort_列(电视、列、反转):
l=[(电视机(k,col),k)代表电视中的k。获取儿童(“”)]
l、 排序(反向=反向)
对于枚举(l)中的索引(val,k):
电视移动(k,,,索引)
标题(col,command=lambda:treeview\u sort\u列(tv,col,not reverse))
def设置单元值(事件):
对于Treeview.selection()中的项:
item_text=Treeview.item(item,“值”)
column=Treeview.identification\u列(event.x)
行=Treeview.identification\u行(event.y)
cn=int(str(列).replace('#','')
rn=int(str(行)。替换('I','')
entryedit=Text(根,宽度=10+(cn-1)*16,高度=1)
入口编辑位置(x=16+(cn-1)*130,y=6+rn*20)
def saveedit():
Treeview.set(item,column=column,value=entryedit.get(0.0,“end”))
entryedit.destroy()
okb.destroy()
okb=ttk.Button(root,text='OK',width=4,command=saveedit)
确定地点(x=90)+
def DeleteCurrentEntry(self, treeView):
curr = treeView.focus()
if '' == curr: return
treeView.delete(curr)
from tkinter import ttk
from tkinter import *
root = Tk()
columns = ("Items", "Values")
Treeview = ttk.Treeview(root, height=18, show="headings", columns=columns) #
Treeview.column("Items", width=200, anchor='center')
Treeview.column("Values", width=200, anchor='center')
Treeview.heading("Items", text="Items")
Treeview.heading("Values", text="Values")
Treeview.pack(side=LEFT, fill=BOTH)
name = ['Item1', 'Item2', 'Item3']
ipcode = ['10', '25', '163']
for i in range(min(len(name), len(ipcode))):
Treeview.insert('', i, values=(name[i], ipcode[i]))
def treeview_sort_column(tv, col, reverse):
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(reverse=reverse)
for index, (val, k) in enumerate(l):
tv.move(k, '', index)
tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))
def set_cell_value(event):
for item in Treeview.selection():
item_text = Treeview.item(item, "values")
column = Treeview.identify_column(event.x)
row = Treeview.identify_row(event.y)
cn = int(str(column).replace('#', ''))
rn = int(str(row).replace('I', ''))
entryedit = Text(root, width=10 + (cn - 1) * 16, height=1)
entryedit.place(x=16 + (cn - 1) * 130, y=6 + rn * 20)
def saveedit():
Treeview.set(item, column=column, value=entryedit.get(0.0, "end"))
entryedit.destroy()
okb.destroy()
okb = ttk.Button(root, text='OK', width=4, command=saveedit)
okb.place(x=90 + (cn - 1) * 242, y=2 + rn * 20)
def newrow():
name.append('to be named')
ipcode.append('value')
Treeview.insert('', len(name) - 1, values=(name[len(name) - 1], ipcode[len(name) - 1]))
Treeview.update()
newb.place(x=120, y=(len(name) - 1) * 20 + 45)
newb.update()
Treeview.bind('<Double-1>', set_cell_value)
newb = ttk.Button(root, text='new item', width=20, command=newrow)
newb.place(x=120, y=(len(name) - 1) * 20 + 45)
for col in columns:
Treeview.heading(col, text=col, command=lambda _col=col: treeview_sort_column(Treeview, _col, False))
root.mainloop()