python - PyQt - QTableView 中的复选框列

标签 python python-2.7 pyqt pandas

我正在从 Pandas 数据框动态创建 QTableView。我有示例代码 here.

我可以创建带有复选框的表格,但我无法让复选框反射(reflect)模型数据,甚至根本无法更改为未选中状态。

我正在遵循之前 question 中的示例代码并以@raorao 的回答为指导。这将在表格中显示方框,但没有任何功能可用。

任何人都可以提出任何更改建议,或者此代码有什么问题。为什么不反射(reflect)模型,为什么不能改变?

请查看我的完整示例代码 here.

编辑一个:根据 Frodon 的评论更新: 使用比较 xxx == 'True' 将字符串更正为 bool

class CheckBoxDelegate(QtGui.QStyledItemDelegate):
    """
    A delegate that places a fully functioning QCheckBox in every
    cell of the column to which it's applied
    """
    def __init__(self, parent):
        QtGui.QItemDelegate.__init__(self, parent)

    def createEditor(self, parent, option, index):
        '''
        Important, otherwise an editor is created if the user clicks in this cell.
        ** Need to hook up a signal to the model
        '''
        return None

    def paint(self, painter, option, index):
        '''
        Paint a checkbox without the label.
        '''
        checked = index.model().data(index, QtCore.Qt.DisplayRole) == 'True'
        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)

        # this will not run - hasFlag does not exist
        #if not index.model().hasFlag(index, QtCore.Qt.ItemIsEditable):
            #check_box_style_option.state |= QtGui.QStyle.State_ReadOnly

        check_box_style_option.state |= QtGui.QStyle.State_Enabled

        QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_CheckBox, check_box_style_option, painter)

    def editorEvent(self, event, model, option, index):
        '''
        Change the data in the model and the state of the checkbox
        if the user presses the left mousebutton or presses
        Key_Space or Key_Select and this cell is editable. Otherwise do nothing.
        '''
        print 'Check Box editor Event detected : ' 
        if not (index.flags() & QtCore.Qt.ItemIsEditable) > 0:
            return False

        print 'Check Box edior Event detected : passed first check' 
        # 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

最佳答案

下面是 PyQt5 的上述相同代码的移植。 在这里发帖是因为在 QT5 中似乎没有另一个 CheckBox Delegate 的工作示例,我正在努力尝试让它工作。希望它对某人有用。

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QModelIndex
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QApplication, QTableView

class CheckBoxDelegate(QtWidgets.QItemDelegate):
    """
    A delegate that places a fully functioning QCheckBox cell of the column to which it's applied.
    """
    def __init__(self, parent):
        QtWidgets.QItemDelegate.__init__(self, parent)

    def createEditor(self, parent, option, index):
        """
        Important, otherwise an editor is created if the user clicks in this cell.
        """
        return None

    def paint(self, painter, option, index):
        """
        Paint a checkbox without the label.
        """
        self.drawCheck(painter, option, option.rect, QtCore.Qt.Unchecked if int(index.data()) == 0 else QtCore.Qt.Checked)

    def editorEvent(self, event, model, option, index):
        '''
        Change the data in the model and the state of the checkbox
        if the user presses the left mousebutton and this cell is editable. Otherwise do nothing.
        '''
        if not int(index.flags() & QtCore.Qt.ItemIsEditable) > 0:
            return False

        if event.type() == QtCore.QEvent.MouseButtonRelease and event.button() == QtCore.Qt.LeftButton:
            # Change the checkbox-state
            self.setModelData(None, model, index)
            return True

        return False


    def setModelData (self, editor, model, index):
        '''
        The user wanted to change the old state in the opposite.
        '''
        model.setData(index, 1 if int(index.data()) == 0 else 0, QtCore.Qt.EditRole)



if __name__ == '__main__':

    import sys

    app = QApplication(sys.argv)

    model = QStandardItemModel(4, 3)
    tableView = QTableView()
    tableView.setModel(model)

    delegate = CheckBoxDelegate(None)
    tableView.setItemDelegateForColumn(1, delegate)
    for row in range(4):
        for column in range(3):
            index = model.index(row, column, QModelIndex())
            model.setData(index, 1)

    tableView.setWindowTitle("Check Box Delegate")
    tableView.show()
    sys.exit(app.exec_())

关于python - PyQt - QTableView 中的复选框列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17748546/

相关文章:

android - Python - 重新打开pygame应用程序后出现黑屏

python - 在数据框中删除一行[有文本而不是数字[可能很简单](pandas、dataframe、python)

Django WSGI 应用程序 SegFault

python - 将大量 float 转换为字符串列表的快速方法

python - 可以在白色文本上添加黑色边框吗?

python - 输入图像的小波二维散射变换

python - Django 模型 "doesn' t 声明一个显式的 app_label”

python-2.7 - 累计整个表并重置为零

python - 在 PyQt 应用程序中处理丢失的包或 DLL

python - 在 Qt5 日历小部件中突出显示日期间隔