canvas - Python Tkinter: Tree selection -


i have created 2 trees idlelib.treewidget in canvas, left , right.

i able print out name of tree node if double-clicked, need double-clicking 1 tree node make tree node visible , selected.

i have simple example here. if double click "level1" on left hand side, "ccc" on right hand side should visible , automatically selected. how do that?

please run following code:

from tkinter import tk, frame, both, canvas xml.dom.minidom import parsestring 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) node in children]       itemlist = [item 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, double click callback must aware of treenode node2 (i can think of global variable, attribute in domtreeitem or bounce component).

then can rely on expand() method of treenode, read children attribute , expand sequentially until element want. note children attribute populated after node has been expanded.

1. quick answer

quick , dirty solution example 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 

2. generic solution

here more general method display arbitrary item in tree.

def reach(node_tree, path):    tokens = path.split("/")    current_node = node_tree    name in tokens:       if len(current_node.children) == 0 , current_node.state != "expanded":          current_node.expand()       candidates = [child 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 way

if self.gettext() == "level1":     reach(node2, "bbb/ccc") 

3. architecture proposal

besides expansion selection of item, propose cleaner architecture through diy observer.

diy observer

(mimic tkinter bind call not rely on tkinter machinery since generating event user data not 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):       callback in self.dbl_click_bindings:          callback.double_click(self.gettext()) 

dedicated component

rely on 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)     


i did not find docs idlelib, in case, can try @ code. following snippet allows find file host module.

import idlelib.treewidget print(idlelib.treewidget.__file__) 

Comments

Popular posts from this blog

apache - Remove .php and add trailing slash in url using htaccess not loading css -

javascript - jQuery show full size image on click -