使用CheckList和Hlist在Python中使用Python自动检查子项

时间:2015-06-23 14:53:57

标签: python tkinter hlist tix

我正在使用Tix在Python中编写一个小程序,它使用复选框功能构建并显示某些文件夹的树视图(只有具有某个xml文件的文件夹)。每个项目都是可以选择(选中)的文件夹或子文件夹。我使用了CheckList和Hlist这个

基于this answer:我设法用复选框显示我想要的文件夹结构。

问题是我需要在检查父项时自动修改嵌套项,这样我就不需要遍历同一父项下的每个项。 我在使用Tix的文档时遇到了很多麻烦。

互联网上似乎存在关于对象和方法的矛盾信息,并且它们通常根据信息来源而不同。我几乎可以肯定,Hlist中没有一个内置功能可以实现这个" autocheck"功能如此纠正我,如果我错了,我将不得不自己开发。

有关此的任何提示或想法? 我将发布所涉及的代码片段和文件夹树视图

首先,我创建清单并找到我感兴趣的目录:

def startCheckList(self):

    self.cl = Tix.CheckList(self.testsFrame, browsecmd=self.selectItem, width=600, height=600)

    self.cl.hlist.configure(indent=20, pady=2, padx=2, bg='#eef4fa', relief=GROOVE, font=self.customFont)
    self.cl.pack()

    for root, dirs, files in os.walk(EA.TESTSFOLDER):
        for aFile in files:
            (fileName, extension) = os.path.splitext(aFile)
            if (fileName == EA.TESTNAME):
                self.testPaths.append(root)

获得文件夹列表后,我将相关元素添加到要显示的Hlist中

def display_paths(self):

    for path in self.testPaths:
        L = []
        path2list(L, path)

        self.create_recursive(L)

    self.cl.autosetmode()

如果元素存在,我不会创建新条目

def create_recursive(self, list):
    path = '.'.join(list)

    if path:

        if self.cl.hlist.info_exists(path) == '1':
            pass

        elif self.cl.hlist.info_exists(path) == '0':

            if list:

                self.create_recursive(list[:-1])
                self.cl.hlist.add(path, text=list[-1])
                self.cl.setstatus(path, "off")

你会怎么做?

View of the program so far

3 个答案:

答案 0 :(得分:2)

好的,因为我找不到任何内置方法,所以我编写了下一个代码:

def selectItem(self, item):

    if self.cl.getstatus(item) == 'on':
        self.autoCheckChildren(item, True)
    if self.cl.getstatus(item) == 'off':
        self.autoCheckChildren(item, False)


def autoCheckChildren(self, i_item, stat):
    item = i_item
    if stat:
        if self.cl.hlist.info_children(item):
            for child in self.cl.hlist.info_children(item):
                self.cl.setstatus(child, "on")
                self.autoCheckChildren(child, True)
    elif not stat:
        if self.cl.hlist.info_children(item):
            for child in self.cl.hlist.info_children(item):
                self.cl.setstatus(child, "off")
                self.autoCheckChildren(child, False)

其中selectItem是选中复选框时调用的函数。我再次使用递归,但这可能不是最好的解决方案。

我发现的另一件事是,当选中一个复选框(清单中的任何一个)时, browsecmd = function 指定的相关功能总是被调用两次。我在某处读到,这是因为按下和释放鼠标被视为两个事件。

这与来自Tkinter的单个检查按钮的行为不同,其中关联函数仅被调用一次。我不知道为什么会有这样的差异。是否可以只调用一次这个函数?

答案 1 :(得分:0)

我知道这是一篇过时的文章,但是经过一段时间的努力之后,我才提出了解决方案。

根据文档,发生多个事件的原因是browsecmd是在鼠标按下,鼠标移动和鼠标按下向上时触发的。因此它将至少触发两次-按下鼠标并按下鼠标。

我已经通过将清单绑定到mouse up事件解决了这个问题,该回调函数设置了一个变量来指示甚至已经接收到mouse up。然后,我的browsecmd函数可以检查此变量的状态,如果它是True,则它将继续(然后再次将变量设置为False)。如果它是False,则会忽略它,因为它不是鼠标上移事件。

下面是我代码的相关部分。

def __init__(self):
    # Insert your own init code here
    self.clMouseUpEvent = False
def checkListClicked(self, event):
    self.clMmouseUpEvent = True
def browseEvent(self, itemID):
    if self.clMmouseUpEvent:
        if self.cl.getstatus(itemID) == 'off':
            status = 'on'
        else:
            status = 'off'
        self.setChildrenStatus(itemID, status)
        self.clMmouseUpEvent = False
def setChildrenStatus(self, itemID, status):
    self.cl.setstatus(itemID, status)
    for childID in self.cl.hlist.info_children(itemID):
        self.setChildrenStatus(childID, status)
def someFunction(self):
    # Insert your own Tix check list set up code here
    self.cl.hlist.config(bg='white', selectbackground='white', selectforeground='black', header=True, browsecmd=self.browseEvent)
    self.cl.hlist.bind("<ButtonRelease-1>", self.checkListClicked)

更新

我随后发现,单击公开指示器也将checkListclicked功能设置clMouseUpEvent设置为True,这导致下一次单击实际复选框以同时处理鼠标和鼠标上移事件。

我现在已经修改了代码,将clMouseUpEvent变量设置为0而不是False,将time.time()设置为True。然后在我的browseEvent中而不是检查clMouseUpEvent == True,而是检查time.time() - self.clMouseUpEvent < 0.01。现在看来工作正常。

答案 2 :(得分:0)

我使用了类似@Son of Beach的方法,但是我还更改了indicatorcmd的{​​{1}}中的hlist。似乎每次按下指示器(折叠按钮)都会运行此命令,并且覆盖了该命令,因此不再触发CheckList

这是代码:

browsecmd

我希望这对将来使用它的人有帮助!