2011-02-24 51 views
15

我一直在使用Tkinter和Tix來編寫一個小程序。 我現在需要一個帶有複選框(checkbuttons)的樹形視圖,所以我可以從樹視圖中選擇項目。 有沒有簡單的方法來做到這一點? 我一直在看ttk.Treeview(),它看起來很容易得到樹視圖,但有沒有辦法將一個checkbutton插入視圖?如何用Python中的複選框創建樹視圖

一個簡單的代碼片段將非常感激。

我不限於ttk。任何事情都會做;只要我有一個例子還是不錯的文檔,我可以讓它工作

回答

17

enter image description here

import Tix 

class View(object): 
    def __init__(self, root): 
     self.root = root 
     self.makeCheckList() 

    def makeCheckList(self): 
     self.cl = Tix.CheckList(self.root, browsecmd=self.selectItem) 
     self.cl.pack() 
     self.cl.hlist.add("CL1", text="checklist1") 
     self.cl.hlist.add("CL1.Item1", text="subitem1") 
     self.cl.hlist.add("CL2", text="checklist2") 
     self.cl.hlist.add("CL2.Item1", text="subitem1") 
     self.cl.setstatus("CL2", "on") 
     self.cl.setstatus("CL2.Item1", "on") 
     self.cl.setstatus("CL1", "off") 
     self.cl.setstatus("CL1.Item1", "off") 
     self.cl.autosetmode() 

    def selectItem(self, item): 
     print item, self.cl.getstatus(item) 

def main(): 
    root = Tix.Tk() 
    view = View(root) 
    root.update() 
    root.mainloop() 

if __name__ == '__main__': 
    main() 
+2

是否有可能涉及以某種方式ttk使複選框看起來本機? – pihentagy 2011-05-13 09:25:57

+3

有沒有一種方法可以在不使用Tix和Tkinter的情況下創建它? – 2014-04-07 15:27:03

+0

我有Python 2.7,我沒有安裝Tix,所以我試圖找到一個替代方案。 – 2014-04-07 15:45:26

5

我與複選框繼承ttk.Treeview一個TreeView類,但複選框沒有ttk.Checkbutton但圖像選中,未選中和三態複選框。

import tkinter as tk 
import tkinter.ttk as ttk 

class CheckboxTreeview(ttk.Treeview): 
    """ 
     Treeview widget with checkboxes left of each item. 
     The checkboxes are done via the image attribute of the item, so to keep 
     the checkbox, you cannot add an image to the item. 
    """ 

    def __init__(self, master=None, **kw): 
     ttk.Treeview.__init__(self, master, **kw) 
     # checkboxes are implemented with pictures 
     self.im_checked = tk.PhotoImage(file='checked.png') 
     self.im_unchecked = tk.PhotoImage(file='unchecked.png') 
     self.im_tristate = tk.PhotoImage(file='tristate.png') 
     self.tag_configure("unchecked", image=self.im_unchecked) 
     self.tag_configure("tristate", image=self.im_tristate) 
     self.tag_configure("checked", image=self.im_checked) 
     # check/uncheck boxes on click 
     self.bind("<Button-1>", self.box_click, True) 

    def insert(self, parent, index, iid=None, **kw): 
     """ same method as for standard treeview but add the tag 'unchecked' 
      automatically if no tag among ('checked', 'unchecked', 'tristate') 
      is given """ 
     if not "tags" in kw: 
      kw["tags"] = ("unchecked",) 
     elif not ("unchecked" in kw["tags"] or "checked" in kw["tags"] 
        or "tristate" in kw["tags"]): 
      kw["tags"] = ("unchecked",) 
     ttk.Treeview.insert(self, parent, index, iid, **kw) 

    def check_descendant(self, item): 
     """ check the boxes of item's descendants """ 
     children = self.get_children(item) 
     for iid in children: 
      self.item(iid, tags=("checked",)) 
      self.check_descendant(iid) 

    def check_ancestor(self, item): 
     """ check the box of item and change the state of the boxes of item's 
      ancestors accordingly """ 
     self.item(item, tags=("checked",)) 
     parent = self.parent(item) 
     if parent: 
      children = self.get_children(parent) 
      b = ["checked" in self.item(c, "tags") for c in children] 
      if False in b: 
       # at least one box is not checked and item's box is checked 
       self.tristate_parent(parent) 
      else: 
       # all boxes of the children are checked 
       self.check_ancestor(parent) 

    def tristate_parent(self, item): 
     """ put the box of item in tristate and change the state of the boxes of 
      item's ancestors accordingly """ 
     self.item(item, tags=("tristate",)) 
     parent = self.parent(item) 
     if parent: 
      self.tristate_parent(parent) 

    def uncheck_descendant(self, item): 
     """ uncheck the boxes of item's descendant """ 
     children = self.get_children(item) 
     for iid in children: 
      self.item(iid, tags=("unchecked",)) 
      self.uncheck_descendant(iid) 

    def uncheck_ancestor(self, item): 
     """ uncheck the box of item and change the state of the boxes of item's 
      ancestors accordingly """ 
     self.item(item, tags=("unchecked",)) 
     parent = self.parent(item) 
     if parent: 
      children = self.get_children(parent) 
      b = ["unchecked" in self.item(c, "tags") for c in children] 
      if False in b: 
       # at least one box is checked and item's box is unchecked 
       self.tristate_parent(parent) 
      else: 
       # no box is checked 
       self.uncheck_ancestor(parent) 

    def box_click(self, event): 
     """ check or uncheck box when clicked """ 
     x, y, widget = event.x, event.y, event.widget 
     elem = widget.identify("element", x, y) 
     if "image" in elem: 
      # a box was clicked 
      item = self.identify_row(y) 
      tags = self.item(item, "tags") 
      if ("unchecked" in tags) or ("tristate" in tags): 
       self.check_ancestor(item) 
       self.check_descendant(item) 
      else: 
       self.uncheck_descendant(item) 
       self.uncheck_ancestor(item) 



if __name__ == '__main__': 
    root = tk.Tk() 
    t = CheckboxTreeview(root, show="tree") 
    t.pack() 
    t.insert("", 0, "1", text="1") 
    t.insert("1", "end", "11", text="1") 
    t.insert("1", "end", "12", text="2") 
    t.insert("12", "end", "121", text="1") 
    t.insert("12", "end", "122", text="2") 
    t.insert("122", "end", "1221", text="1") 
    t.insert("1", "end", "13", text="3") 
    t.insert("13", "end", "131", text="1") 
    root.mainloop() 

CheckboxTreeview的改進版本是ttkwidgets模塊中提供。

+0

這個想法很好,但我不確定它在「Treeview」中的某些條目之後如何擴展。即使圖像很小,它仍然需要一小塊內存。 – rbaleksandar 2017-08-07 19:12:47

+0

@rbaleksandar我明白你的觀點,它不適用於大型樹木,但如果你沒有數百種物品,它會比Tix樹更好。 – 2017-08-08 07:58:01

+0

爲什麼這不是一個可擴展的解決方案?圖像是否複製到每個treenode?我希望只有圖像數據的參考是沿節點共享的。所以內存中只有2張圖片。或者我錯了? – Hatatister 2017-09-20 16:21:02

相關問題