7

我正在尝试创建一个树小部件,该小部件基本上允许用户查看数据的各种细分,并可以选择删除某些项目。为了做到这一点,我希望有与每个顶级项目和每个子项关联的复选框,以便用户可以选择要删除的顶级项目(以及该顶级项目的所有子项)。或者要删除哪些特定的孩子。为了让您更好地了解,我创建了一个示例,其中 [x] 表示选中的复选框, [ ] 表示空复选框:

>Beverages Allowed in Stadium [ ]
    Soda                      [ ]
    Water                     [ ]
    Tea                       [ ]
    Spirits                   [X]
    Ale                       [ ]

>Tickets                      [X]
    Row A                     [X]
    Row B                     [X]
    Row C                     [X]
    Lawn                      [X]

有什么建议如何实施吗?我不知道它在难度方面是否有所不同,但我已经为复选框分配了一个单独的列。

4

4 回答 4

23

除了您提供的答案ItemIsTristate之外,您还可以通过使用父元素上的标志来简化逻辑。

from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import sys

def main(): 
    app     = QApplication (sys.argv)
    tree    = QTreeWidget ()
    headerItem  = QTreeWidgetItem()
    item    = QTreeWidgetItem()

    for i in xrange(3):
        parent = QTreeWidgetItem(tree)
        parent.setText(0, "Parent {}".format(i))
        parent.setFlags(parent.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        for x in xrange(5):
            child = QTreeWidgetItem(parent)
            child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
            child.setText(0, "Child {}".format(x))
            child.setCheckState(0, Qt.Unchecked)
    tree.show() 
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

最重要的三行代码是:

parent.setFlags(parent.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)

这将父元素设置为三态复选框。

child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
child.setCheckState(0, Qt.Unchecked)

这些将孩子设置为可选择并将默认设置为未选中。如果孩子的复选框没有被赋予状态,复选框元素不会出现。


上面的代码构建了一个非常简单的树。

简单树

但是,如果我选中父元素上的复选框,则会自动选择所有子元素:

已选择父级

如果,我想取消选择一个孩子,父母进入部分选择(三态):

三态

如果所有子级都未选中,则父级将自动取消选中。如果未选择父级,则所有子级也将自动取消选择。

于 2015-07-10T14:04:44.327 回答
5

我将@andy 的精彩示例移植到 PyQt5:

from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.Qt import Qt
import sys

def main(): 
    app     = QtWidgets.QApplication(sys.argv)
    tree    = QtWidgets.QTreeWidget()
    headerItem  = QtWidgets.QTreeWidgetItem()
    item    = QtWidgets.QTreeWidgetItem()

    for i in range(3):
        parent = QtWidgets.QTreeWidgetItem(tree)
        parent.setText(0, "Parent {}".format(i))
        parent.setFlags(parent.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        for x in range(5):
            child = QtWidgets.QTreeWidgetItem(parent)
            child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
            child.setText(0, "Child {}".format(x))
            child.setCheckState(0, Qt.Unchecked)
    tree.show() 
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

截屏

于 2019-09-06T10:14:20.977 回答
2

QTreeWidgetItem实际上有一个内置的复选框,您可以很容易地使用它。

例如:

item = QTreeWidgetItem(self.treeWidget)

item.setCheckState(0, QtCore.Qt.Unchecked)
于 2015-07-10T13:52:14.757 回答
1

这不是您问题的答案,而是您拥有复选框后如何使用它们。我从标记为正确的答案中使用了上面的示例。它起作用了,但是当我试图找到如何知道标记了哪些复选框时,我遇到了很多问题。经过大量搜索,我找到了一个适合我的解决方案,因为我看到没有很多文档,所以我想为将来留下记录。顺便提一下,我使用了几种解决方案作为 invisibleRootItem 来找到父级的子级,但这没有用。

我最终使用带有标志 QtGui.QTreeWidgetItemIterator.Checked 的类 QTreeWidgetItemIterator 来检索标记的复选框的文本,这样我就可以继续工作了。

def vrfs_selected(self):
    iterator = QtGui.QTreeWidgetItemIterator(self.tree, QtGui.QTreeWidgetItemIterator.Checked)
    while iterator.value():
        item = iterator.value()
        print (item.text(0))    
        iterator += 1

文档链接http://ftp.ics.uci.edu/pub/centos0/ics-custom-build/BUILD/PyQt-x11-gpl-4.7.2/doc/html/qtreewidgetitemiterator.html和示例https ://riverbankcomputing.com/pipermail/pyqt/20​​14-May/034315.html

于 2017-01-01T21:59:18.290 回答