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
方法来绘制QRadioButton
和 editorEvent
方法来捕获点击事件并根据情况更改其他项目的状态。
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()
这个问题参考@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
方法来绘制QRadioButton
和 editorEvent
方法来捕获点击事件并根据情况更改其他项目的状态。
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()