PyQt [QTreeWidget]:如何为项目添加单选按钮?

PyQt [QTreeWidget]: How to add Radiobutton for items?

这个问题参考@Andy的回答

@Andy 展示了如何将 CheckBox 添加到 QTreeWidget 中,效果非常好。

我想问一下,如何把RadioButton加到QTreeWidget中? ----而且,这对我来说更难,如何只使一个项目可选择,尽管它们在不同的groups

我将@Andy 中的代码重写为 PyQt5:

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

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

    for i in range(3):
        parent = QTreeWidgetItem(tree)
        parent.setText(0, "Parent {}".format(i))
        parent.setFlags(parent.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        for x in range(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()

上面代码的运行结果:

更新:期望的结果应该如下所示...

非常感谢任何帮助!谢谢!

如果你想建立一个QRadioButton并且它在一个组中是独占的,一个可能的解决方案是实现一个委托,在这个委托中我们将覆盖paint方法来绘制QRadioButtoneditorEvent 方法来捕获点击事件并根据情况更改其他项目的状态。

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


class Delegate(QStyledItemDelegate):
    def paint(self, painter, option, index):
        if not index.parent().isValid():
            QStyledItemDelegate.paint(self, painter, option, index)
        else:
            widget = option.widget
            style = widget.style() if widget else QApplication.style()
            opt = QStyleOptionButton()
            opt.rect = option.rect
            opt.text = index.data()
            opt.state |= QStyle.State_On if index.data(Qt.CheckStateRole) else QStyle.State_Off
            style.drawControl(QStyle.CE_RadioButton, opt, painter, widget)

    def editorEvent(self, event, model, option, index):
        value = QStyledItemDelegate.editorEvent(self, event, model, option, index)
        if value:
            if event.type() == QEvent.MouseButtonRelease:
                if index.data(Qt.CheckStateRole) == Qt.Checked:
                    parent = index.parent()
                    for i in range(model.rowCount(parent)):
                        if i != index.row():
                            ix = parent.child(i, 0)
                            model.setData(ix, Qt.Unchecked, Qt.CheckStateRole)

        return value


def main():
    app = QApplication(sys.argv)
    tree = QTreeWidget()
    tree.setItemDelegate(Delegate())

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

    tree.expandAll()
    tree.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()