在 PySide/PyQt 中查看带有复选框列的 QStandardItemModel? [英] View QStandardItemModel with column of checkboxes in PySide/PyQt?

查看:69
本文介绍了在 PySide/PyQt 中查看带有复选框列的 QStandardItemModel?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 QStandardItemModelQTreeView,并且希望其中一列只有复选框(没有文本,只有复选框).此已针对QAbstractItemModel 进行了讨论.我试图在那里实施解决方案(请参阅下面的 SSCCE),但在视图的第一行中只显示一个复选框.我不确定需要为复选框添加什么额外的魔法才能显示在每一行中.

I have a QTreeView of a QStandardItemModel, and want one column to be checkboxes only (no text, just checkboxes). This has been discussed for QAbstractItemModel. I have tried to implement the solution there (see SSCCE below), but only a single checkbox shows up, in the first row of the view. I am not sure what extra magic needs to be added for the checkbox to show up in every row.

请注意,如此相关问题,我想要一列复选框没有文本字段,所以简单地将 setCheckable(True) 应用于列中的每个项目是不够的,因为这会留下一个 (空)复选框旁边的文本字段.

Note, as discussed at this related question, I want a column of checkboxes with no text fields, so simply applying setCheckable(True) to each item in a column will not be enough, as that leaves an (empty) text field next to the checkbox.

SSCCE

# -*- 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_())

推荐答案

列数有问题:只有两列,除了顶级项.委托被设置在第三列,所以它只为顶级项目设置.

There is a problem with the number of columns: there's only two columns, except for the top level items. The delegate is set on the third column, so it's only set for the top level items.

你定义你的线条:

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

很明显,这里只有两列.但在此之前,您可以使用以下命令设置标题标签:

Here, clearly, there's only two columns. But before that, you set the header labels with:

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

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

I guess this line set that there is three columns for the top level items, but it doesn't have any effect on the child items.

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

If you directly create lines with three items, your problem is solved:

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

这篇关于在 PySide/PyQt 中查看带有复选框列的 QStandardItemModel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆