Python Tkinter:树选择 [英] Python Tkinter: Tree selection
问题描述
我已经在Canvas中左右创建了两个带有idlelib.TreeWidget的树。
我也可以打印出树节点的名称,点击,但我需要的是双击一个树节点将使一个树节点可见和选择。
我有一个简单的例子。如果双击左侧的level1,右侧的ccc应该可见并自动选择。
请运行以下代码:
从Tkinter导入Tk,Frame,BOTH,Canvas
从xml.dom.minidom导入parseString
从idlelib.TreeWidget导入TreeItem,TreeNode
class DomTreeItem(TreeItem):
def __init __(self,node):
self.node = node
def GetText(self):
node = self.node
if node.nodeType == node .ELEMENT_NODE:
return node.nodeName
elif node.nodeType == node.TEXT_NODE:
return node.nodeValue
def IsExpandable(self):
node = self .node
return node.hasChildNodes()
def GetSubList(self):
parent = self.node
children = parent.childNodes
prelist = [DomTreeItem )for node in children]
itemlist = [item for item in prelist if item.GetText()。strip()]
return itemlist
def OnDoubleClick(self):
print self.node.nodeName
left ='''
< level0>
< level1 />
< / level0>
'''
right ='''
< aaa>
< bbb> < ccc /> < / bbb>
< / aaa>
'''
类应用程序(框架):
def __init __(self,parent):
Frame .__ init __(self,parent)
self .parent = parent
self.parent.geometry('%dx%d +%d +%d'%(800,300,0,0))
self.parent.resizable(0,0)
dom = parseString(left)
item = DomTreeItem(dom.documentElement)
self.canvas = Canvas(self,bg =cyan)
self.canvas .grid(column = 0,row = 0,sticky ='NSWE')
node = TreeNode(self.canvas,None,item)
node.update()
dom2 = parseString(right)
item2 = DomTreeItem(dom2.documentElement)
self.canvas2 = Canvas(self,bg =yellow)
self.canvas2.grid(column = row = 0,sticky ='NSWE')
node2 = TreeNode(self.canvas2,None,item2)
node2.update()
self.pack(fill = BOTH ,expand = True)
def main():
root = Tk()
应用程序(root)
root.mainloop()
if __name__ =='__main__':
main()
首先,你的双击回调必须知道你的TreeNode node2
(我可以想到全局变量,属性在DomTreeItem或bounce到另一个组件)。
然后你可以依赖TreeNode的 expand()
方法,读取 children
属性,并依次展开,直到您想要的元素。请注意, children
属性只在节点扩展后填充。
1。快速回答
您提供的示例的快速和脏的解决方案
class DomTreeItem(TreeItem):
def OnDoubleClick(self):
if self.GetText()==level1:
node2.expand()
node2.children [ 0] .expand()
node2.children [0] .children [0] .select()
[...] ):
def __init __(self,parent):
global node2
2 。通用解决方案
这是一个更常见的在树中显示任意项的方法。
def reach(node_tree,path):
tokens = path.split(/)
current_node = node_tree
用于tokens中的名称:
如果len (current_node.children)== 0和current_node.state!=expanded:
current_node.expand()
candidates = [child_node.children中child的子节点,如果child.item.GetText = name]
if len(candidates)== 0:
print(did not find'{}'。format(name))
return
current_node = candidates [ 0]
current_node.select()
您可以这样使用
if self.GetText()==level1:
reach(node2,bbb / ccc)
3。建筑方案
除了扩展项目的选择外,我还建议您通过DIY观察者建立更清洁的建筑。
DIY观察器
(模仿Tkinter bind
tkinter机械,因为生成带有用户数据的事件未正确处理)
class DomTreeItem(TreeItem):
def __init __(self,node,dbl_click_bindings = None):
self.node = node
self.dbl_click_bindings = if(dbl_click_bindings == None)else dbl_click_bindings
[...]
def OnDoubleClick(self):
self.fireDblClick()
def bind(self,event,callback):
'''mimic tkinter bind
'''
if(event!=<< TreeDoubleClick>>):
print(err ...)
self.dbl_click_bindings.append(callback)
def fireDblClick(self):
for callback in self.dbl_click_bindings:
callback.double_click (self.GetText())
专用组件 b
$ b
依赖于上述的覆盖方法。
class TreeExpander:
def __init __(self,node_tree,matching_items):
self.node_tree = node_tree
self.matching_items = matching_items
def double_click(self,item_name):
print(double_click }