Python Tkinter:树选择

2024-05-14 09:24:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我用idlelib.TreeWidget公司在画布上,左右。在

如果双击,我也可以打印出树节点的名称,但我需要的是双击一个树节点将使某个树节点可见并被选中。在

我有一个简单的例子。如果双击左侧的“level1”,则右侧的“ccc”应可见并自动选中。你怎么做到的?在

请运行以下代码:

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()  

Tags: fromimportselfnodereturn节点defitem
1条回答
网友
1楼 · 发布于 2024-05-14 09:24:42

首先,双击回调必须知道TreeNode node2(我可以想到全局变量、DomTreeItem中的属性或反弹到另一个组件)。在

然后可以依赖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()

[...]

class Application(Frame):
    def __init__(self, parent):
        global node2

2。通用解决方案

这里有一个更通用的方法来显示树中的任意项。在

^{pr2}$

你可以这样用

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

3。架构方案

除了扩展一个项目的选择,我建议你通过一个DIY观察者一个更干净的架构。在

DIY观察者

(模拟Tkinterbind调用,但自generating event with user data is not properly handled起不依赖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())

专用组件

依赖于上述reach方法。在

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])

订阅

class Application(Frame):
   def __init__(self, parent):
      [...]

      expander = TreeExpander(node2, {
         "level1": "bbb/ccc"
         })
      item.bind("<<TreeDoubleClick>>", expander)    


我没有找到idlelib的文档,在这种情况下,您可以尝试查看代码。下面的代码片段允许您找到该模块的宿主文件。
import idlelib.TreeWidget
print(idlelib.TreeWidget.__file__)

相关问题 更多 >

    热门问题