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 d
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 the children
attribute and expand sequentially until the element you want. Note that children
attribute is only populated after the node has been expanded.
Quick and dirty solution for the example you have provided
class DomTreeItem(TreeItem):
def OnDoubleClick(self):
if self.GetText() == "level1":
node2.expand()
node2.children[0].expand()
node2.children[0].children[0].select()
[...]
class Application(Frame):
def __init__(self, parent):
global node2
Here is a more general method to display an arbitrary item in a tree.
def reach(node_tree, path):
tokens = path.split("/")
current_node = node_tree
for name in tokens:
if len(current_node.children) == 0 and current_node.state != "expanded":
current_node.expand()
candidates = [child for child in current_node.children if child.item.GetText() == name]
if len(candidates) == 0:
print("did not find '{}'".format(name))
return
current_node = candidates[0]
current_node.select()
You might use it this way
if self.GetText() == "level1":
reach(node2, "bbb/ccc")
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)
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())
Dedicated component
Rely on the reach method presented above.
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 ({0})".format(item_name))
if (item_name in self.matching_items):
reach(self.node_tree, self.matching_items[item_name])
Subscription
class Application(Frame):
def __init__(self, parent):
[...]
expander = TreeExpander(node2, {
"level1": "bbb/ccc"
})
item.bind("<<TreeDoubleClick>>", expander)
import idlelib.TreeWidget
print(idlelib.TreeWidget.__file__)