[英]Autocheck children items in Tix with Python using CheckList and Hlist
我正在使用 Tix 在 Python 中編寫一個小程序,該程序構建並顯示具有復選框功能的某些文件夾(只有其中包含某個 xml 文件的文件夾)的樹視圖。 每個項目都是一個可以選擇(選中)的文件夾或子文件夾。 我為此使用了 CheckList 和 Hlist
基於這個答案:我設法用復選框顯示了我想要的文件夾結構。
問題是,每當檢查父項時,我都需要自動檢查嵌套項,這樣我就不需要檢查同一父項下的每個項。 我在使用 Tix 的文檔時遇到了很多麻煩。
互聯網上似乎有關於對象和方法的相互矛盾的信息,並且根據信息來源的不同,它們往往會有所不同。 我幾乎可以肯定,Hlist 中沒有啟用此“自動檢查”功能的內置功能,因此如果我錯了,請糾正我,我將不得不自己開發它。
對此有任何提示或想法嗎? 我將發布涉及的代碼片段和文件夾樹視圖
首先,我創建清單並找到我感興趣的目錄:
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")
你將如何進行?
好的,因為我找不到任何內置方法,所以我編寫了下一個代碼:
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 是選中復選按鈕時調用的函數。 我再次使用遞歸,但這可能不是最好的解決方案。
Another thing that I found is that when selecting a checkbox (any one from the checklist) the associated function specified by browsecmd=function is always called twice. 我在某處讀到這是因為按下和釋放鼠標被視為兩個事件。
這與來自 Tkinter 的單個 checkbutton 的行為不同,其中關聯的函數只被調用一次。 我不知道為什么會有這樣的差異。 是否可以只調用一次這個函數?
我知道這是一個舊帖子,但是在為此苦苦掙扎了一段時間后,我剛剛想出了一個解決方案。
根據文檔,多個事件的原因是browsecmd
是在鼠標按下、鼠標移動和鼠標按下時觸發的。 所以它至少會被觸發兩次 - 鼠標按下和鼠標抬起。
我通過將清單綁定到鼠標抬起事件解決了這個問題,並通過回調設置了一個變量來指示甚至已經收到鼠標抬起。 我的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
。 這現在似乎工作正常。
我用了一個類似的方法作為海灘@Son做了,但是我也改變了indicatorcmd
在hlist
中的CheckList
。 似乎每次按下指示器(折疊按鈕)時都會運行此命令,並覆蓋它使其不再觸發browsecmd
。
這是代碼:
def toggle_path(tree: tix.CheckList, path: str):
# delay clicks to not trigger it twice
if time.time() - self._event_toggle > App.TOGGLE_EVENT_DELAY:
getattr(tree, tree.getmode(path))(path)
self._event_toggle = time.time()
self.checklist = tix.CheckList(self.master,
browsecmd=lambda path: self.select(self.checklist, path),
command=lambda path: self.select(self.checklist, path))
self.checklist.hlist.configure(indicatorcmd=lambda path: toggle_path(self.to_tree, path))
我希望這可以對將來使用它的人有所幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.