I have created 2 trees with idlelib.TreeWidget in Canvas, left and right.
I am also able to print out the name of a tree node if double-clicked, but what I need is double-clicking one tree node will make a certain tree node visible and selected.
I have a simple example here. If you double click "level1" on the left hand side, "ccc" on the right hand side should be visible and automatically selected. How do you do that?
Please run the following code:
from Tkinter import Tk, Frame, BOTH, Canvas
from xml.dom.minidom import parseString
from idlelib.TreeWidget import 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(node) 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>
'''
class Application(Frame):
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 = 1, row = 0, sticky = 'NSWE')
node2 = TreeNode(self.canvas2, None, item2)
node2.update()
self.pack(fill = BOTH, expand = True)
def main():
root = Tk()
Application(root)
root.mainloop()
if __name__ == '__main__':
main()
First, your double click callback must be aware of your TreeNode
node2
(I can think of global variable, attribute in DomTreeItem or bounce to another component).Then you can rely on
expand()
method of TreeNode, read thechildren
attribute and expand sequentially until the element you want. Note thatchildren
attribute is only populated after the node has been expanded.1. Quick answer
Quick and dirty solution for the example you have provided
2. Generic solution
Here is a more general method to display an arbitrary item in a tree.
You might use it this way
3. Architecture proposal
Besides the expansion an selection of an item, I propose you a cleaner architecture through a DIY observer.
DIY Observer
(mimic the Tkinter
bind
call but does not rely on tkinter machinery since generating event with user data is not properly handled)Dedicated component
Rely on the reach method presented above.
Subscription
I did not find docs for idlelib, in this case, you can try to look at the code. The following snippet allows you to find which file host this module.