我正在使用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")
你会怎么做?
答案 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
我希望这对将来使用它的人有帮助!