在PySide / PyQt中查看带有复选框列的QStandardItemModel?

时间:2015-07-17 14:25:10

标签: qt pyqt pyside

我有一个QTreeView QStandardItemModel,并希望只有一列是复选框(没有文字,只有复选框)。 QAbstractItemModelsetCheckable(True)。我试图在那里实现解决方案(参见下面的SSCCE),但在视图的第一行中只显示一个复选框。我不确定需要添加多少魔法才能使复选框显示在每一行中。

请注意,正如has been discussed所述,我想要一列没有文字字段的复选框,因此只需将# -*- coding: utf-8 -*- from PySide import QtGui, QtCore import sys class CheckBoxDelegate(QtGui.QStyledItemDelegate): def __init__(self, parent = None): QtGui.QStyledItemDelegate.__init__(self, parent) def createEditor(self, parent, option, index): return None def paint(self, painter, option, index): checked = bool(index.model().data(index, QtCore.Qt.DisplayRole)) check_box_style_option = QtGui.QStyleOptionButton() if (index.flags() & QtCore.Qt.ItemIsEditable) > 0: check_box_style_option.state |= QtGui.QStyle.State_Enabled else: check_box_style_option.state |= QtGui.QStyle.State_ReadOnly if checked: check_box_style_option.state |= QtGui.QStyle.State_On else: check_box_style_option.state |= QtGui.QStyle.State_Off check_box_style_option.rect = self.getCheckBoxRect(option) QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_CheckBox, check_box_style_option, painter) def editorEvent(self, event, model, option, index): if not (index.flags() & QtCore.Qt.ItemIsEditable) > 0: return False # Do not change the checkbox-state if event.type() == QtCore.QEvent.MouseButtonRelease or event.type() == QtCore.QEvent.MouseButtonDblClick: if event.button() != QtCore.Qt.LeftButton or not self.getCheckBoxRect(option).contains(event.pos()): return False if event.type() == QtCore.QEvent.MouseButtonDblClick: return True elif event.type() == QtCore.QEvent.KeyPress: if event.key() != QtCore.Qt.Key_Space and event.key() != QtCore.Qt.Key_Select: return False else: return False # Change the checkbox-state self.setModelData(None, model, index) return True def setModelData (self, editor, model, index): newValue = not bool(index.model().data(index, QtCore.Qt.DisplayRole)) model.setData(index, newValue, QtCore.Qt.EditRole) def getCheckBoxRect(self, option): check_box_style_option = QtGui.QStyleOptionButton() check_box_rect = QtGui.QApplication.style().subElementRect(QtGui.QStyle.SE_CheckBoxIndicator, check_box_style_option, None) check_box_point = QtCore.QPoint (option.rect.x() + option.rect.width() / 2 - check_box_rect.width() / 2, option.rect.y() + option.rect.height() / 2 - check_box_rect.height() / 2) return QtCore.QRect(check_box_point, check_box_rect.size()) #BUILD THE TREE app = QtGui.QApplication(sys.argv) model = QtGui.QStandardItemModel() model.setHorizontalHeaderLabels(['Title', 'Summary', 'Checkbox']) rootItem = model.invisibleRootItem() #Adding branches and leaves to root item0 = [QtGui.QStandardItem('Title0'), QtGui.QStandardItem('Summary0')] item00 = [QtGui.QStandardItem('Title00'), QtGui.QStandardItem('Summary00')] rootItem.appendRow(item0) item0[0].appendRow(item00) treeView= QtGui.QTreeView() treeView.setModel(model) treeView.expandAll() treeView.show() #PUT THE CHECKBOX IN COLUMN 2 myDelegate = CheckBoxDelegate() treeView.setItemDelegateForColumn(2, myDelegate) sys.exit(app.exec_()) 应用于列中的每个项目就不够了,因为这会在复选框旁边留下一个(空)文本字段。

SSCCE

public class CommentViewModel
{
    public string Comment { get; set; }
    public string Email { get; set; }
    public string Actid { get; set; }
}

public IHttpActionResult PostComment([FromBody]CommentViewModel model)
{
    string status = ...;
    return Ok(status);
}

2 个答案:

答案 0 :(得分:2)

列数存在问题:除了顶级项目之外,只有两列。委托设置在第三列,因此它仅设置为顶级项目。

您可以使用以下内容定义行:

item1 = [QtGui.QStandardItem('Title1'), QtGui.QStandardItem('Summary1')]

在这里,显然只有两列。但在此之前,您将标题标签设置为:

model.setHorizontalHeaderLabels(['Title', 'Summary', 'Checkbox'])

我想这一行设置了顶级项目有三列,但它对子项目没有任何影响。

如果直接创建包含三个项目的行,则问题就解决了:

item0 = [QtGui.QStandardItem('Title0'), QtGui.QStandardItem('Summary0'), QtGui.QStandardItem()]
item00 = [QtGui.QStandardItem('Title00'), QtGui.QStandardItem('Summary00'), QtGui.QStandardItem()]

答案 1 :(得分:-1)

我认为您根本不需要项目委托。只需考虑使用QStandardItem::setFlags()函数以及添加到树中的每个Qt::ItemIsUserCheckable的{​​{1}}标记。