前言:作為一只菜鳥,無法像諸位大神那樣在描述問題之前深入淺出地介紹背景TAT,只能默認來看這篇文章的人對QTreeWidget已經有過了解,想在python中實現對其下所有Item的遍歷。
由於試手的軟件里需要實現按下相關功能鍵后,刪除QTreeWidget中打勾(即checked)的item。所以需要遍歷所有item檢查狀態。在閱讀QT文檔的時候(因為PyQt5的Reference Guide還沒更新......所以只好點它給的C++ Documentation的鏈接),發現QT其實有提供一個迭代器——QTreeWidgetItemIterator,在其官方文檔里,它是這么實現功能的:
1 QTreeWidgetItemIterator it(treeWidget); 2 while (*it) { 3 if ((*it)->text(0) == itemText) 4 (*it)->setSelected(true); 5 ++it; 6 }
......
對於一個菜鳥,要根據這個一眼看出Python里要怎么改實在太有難度了啊!——所以我就先去必應了下有沒有其他方法。發現大家在PyQt下大多是用這個方法:
1、先用QTreeWidget的topLevelItemCount()獲得topLevelItem的數量
2、然后用for循環和topLevelItem(int index)獲得頂層的結點
3、再用QTreeWidgetItem里的功能獲得頂層結點下的children結點
由於一直被教導要追求簡潔,以及看着QT明明有現成的功能卻不能用,所以在英文搜索也沒找到滿意答案后(用的還是必應,google用不了),我又重新回來琢磨QTreeWidgetItemIterator,在花了許多時間仍無進展的情況下,只要先直接用代碼試驗,失敗了N次之后,被一個無關的搜索結果提醒可以在Python交互行里用help看它有沒有在這提供文檔說明,一試之下,果然有:
class QTreeWidgetItemIterator(sip.simplewrapper) | QTreeWidgetItemIterator(QTreeWidgetItemIterator) | QTreeWidgetItemIterator(QTreeWidget, QTreeWidgetItemIterator.IteratorFlags flags=QTreeWidgetItemIterator.All) | QTreeWidgetItemIterator(QTreeWidgetItem, QTreeWidgetItemIterator.IteratorFlags flags=QTreeWidgetItemIterator.All) | | Method resolution order: | QTreeWidgetItemIterator | sip.simplewrapper | builtins.object | | Methods defined here: | | __iadd__(self, value, /) | Return self+=value. | | __isub__(self, value, /) | Return self-=value.
(文檔未完,這里只放本問題需要的那一小部分)
一下子看到了問題解決的曙光!!但是,作為一只菜鳥,我雖然看到了Methods,但沒有立刻把它和C++里的指針聯系起來,仍然在糾結PyQt下的QTreeWidgetItemIterator返回的應該是啥(用isinstance
判斷它既不是迭代器,也不是可迭代的)......
所以再撞了幾次牆后,我才突然反應了過來,最終實現代碼如下:
def delSelected(self): item = QtWidgets.QTreeWidgetItemIterator(self.treeWidget) #該類的value()即為QTreeWidgetItem while item.value():if item.value().checkState(0) == QtCore.Qt.Checked: #參考網上的方法,判斷有無父母結點后再分別操作的那個,實在找不到更直接的 self.deleteNode() #因為我這里是刪除了結點,刪除后結點位置發生變化,所以要向后退一步 item = item.__isub__(1) #到下一個節點 item = item.__iadd__(1)
非常簡單有沒有!官方提供這個功能就是有用有沒有!!對於我這種不用考慮遍歷效率的菜鳥太好用的有沒有!!
問題解決了,本文也到此結束,紀念我那抓狂的一個下午。感謝您讀到了這里!如有錯誤請指正!