簡體   English   中英

使用 CheckList 和 Hlist 使用 Python 自動檢查 Tix 中的子項

[英]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而不是Falsetime.time()而不是True 然后在我的browseEvent而不是檢查clMouseUpEvent == True它檢查time.time() - self.clMouseUpEvent < 0.01 這現在似乎工作正常。

我用了一個類似的方法作為海灘@Son做了,但是我也改變了indicatorcmdhlist中的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM