I am writing a small program in Python using Tix that builds and displays a tree view of certain folders (only the ones having a certain xml file in them) with checkbox capabilities. Every Item is a folder or subfolder that can be selected (checked). I used CheckList and Hlist for this
Based on this answer: I managed to display the folder structure that I want with checkboxes.
The problem is that I need the nested Items to be autochecked whenever a parent is checked so that I do not need to go through every Item under the same parent Item. I am having a lot of trouble with the documentation with Tix.
There seems to be contradictory information on the internet about the objects and methods, and they are often different depending on the source of information. I am almost certain that there is not a built-in feature in Hlist that enables this "autocheck" function so correct me if I am wrong I would have to develop it myself.
Any hints or ideas on this? I will post the pieces of code involved and the folder treeview
First I create the Checklist and find the directories I am interested in:
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)
Once I have the folder list I add the associated elements to the Hlist to be displayed
def display_paths(self):
for path in self.testPaths:
L = []
path2list(L, path)
self.create_recursive(L)
self.cl.autosetmode()
If an element exists I do not create a new entry
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")
How would you proceed?
I know this is an old post, but after struggling with this for a while, I've just come up with a solution.
According to the documentation, the reason for multiple events is that the browsecmd
is triggered for mouse button down, mouse moved and mouse button up. So it will be fired at least twice - for mouse down and mouse up.
I've solved this problem by binding the checklist to the mouse up event, with a callback that sets a variable to indicate that a mouse up even has been received. My browsecmd
function can then check the status of this variable, and if it is True
, then it proceeds (AND THEN SETS THE VARIABLE TO False
AGAIN). If it is False
it ignores it because it is not a mouse up event.
Below is the relevant part of my code.
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)
UPDATE:
I subsequently found that clicking on the disclosure indicators also fired the checkListclicked
function setting clMouseUpEvent
to True
which then resulted in the next click to an actual checkbox to process both the mouse down and mouse up events.
I have now modified my code to set the clMouseUpEvent
variable to 0
instead of False
and time.time()
instead of True
. Then in my browseEvent
instead of checking for clMouseUpEvent == True
it checks for time.time() - self.clMouseUpEvent < 0.01
. This seems to be working OK now.