1

我有一个qtablewidgetitem,里面有一个QCheckbox

禁用时qtablewigetitem如下

    flags = self.item(row+1, self.columns["USER_ACCESS"]).flags()
    flags |= QtCore.Qt.ItemIsSelectable
    flags |= QtCore.Qt.ItemIsEditable
    flags |= QtCore.Qt.ItemIsEnabled
    self.item(row+1, self.columns["USER_ACCESS"]).setFlags(flags)

它已被禁用,我无法单击它,但它仍处于启用状态时被显示。

我想用灰色显示它

更新:

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.QStyledItemDelegate.__init__(self, parent)
        self.parent = 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.data() #.toBool()
        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)

        #if not index.model().hasFlag(index, 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.
        '''
        if not (index.flags() & QtCore.Qt.ItemIsEditable) > 0:
            return False

        # Do not change the checkbox-state
        if event.type() == QtCore.QEvent.MouseButtonPress:
          return False
        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):
        '''
        The user wanted to change the old state in the opposite.
        '''
        newValue = QtCore.Qt.Checked if not index.data() else QtCore.Qt.Unchecked
        model.setData(index, newValue, QtCore.Qt.EditRole)
        self.parent.sort()
        self.parent.sort()

    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())

这就是我把它放在 QTableWidgetItem 中的方法

def delegate(self, column, delegater):
    self.setItemDelegateForColumn(column, delegater)
    pass
4

1 回答 1

3

改为使用^

flags ^= QtCore.Qt.ItemIsEnabled

|是按位或。它所做的是将启用标志打开,而不管其原始状态如何。 ^将切换它。

如果您想关闭标志,无论其原始状态如何,只需将其与它的 COMPLIMENT (~) 与 (&) 一起使用,如下所示:

flags = flags & ~QtCore.Qt.ItemIsEnabled

您可以将这些原则应用于您想要关闭或打开的任何标志,例如QtCore.Qt.ItemIsSelectable等。

在您的情况下,代码将类似于:

flags = self.item(row+1, self.columns["USER_ACCESS"]).flags()
flags &= ~QtCore.Qt.ItemIsSelectable
flags &= ~QtCore.Qt.ItemIsEditable
flags &= ~QtCore.Qt.ItemIsEnabled
self.item(row+1, self.columns["USER_ACCESS"]).setFlags(flags)

查看更多详细信息: https ://wiki.python.org/moin/BitwiseOperators

涉及该主题的另一个精彩答案(非常有用): 如何在 PyQt 中的自定义 Qt.ItemFlags 实例中找到特定的 Qt.ItemFlag 出现?

UPDATE-1:如果您的单元格有小部件 形式的项目(例如QCheckBox),您可能希望以不同的方式处理它。您可能想要禁用相应的小部件。因此,在您的情况下,您会执行以下操作:

my_checkbox_item = self.cellWidget(row+1, self.columns["USER_ACCESS"])
my_checkbox_item.setEnabled(False)

UPDATE-2: 因为,您现在已经用更多代码更新了您的问题,这里有另一个更新:在您的paint方法中,您必须应用与本答案第一部分所示相同的按位运算原则。因此,您必须执行以下操作:

    if (index.flags() & QtCore.Qt.ItemIsEditable) > 0:
        check_box_style_option.state |= QtGui.QStyle.State_Enabled
        check_box_style_option.state &= ~QtGui.QStyle.State_ReadOnly
    else:
        check_box_style_option.state &= ~QtGui.QStyle.State_Enabled
        check_box_style_option.state |= QtGui.QStyle.State_ReadOnly

..并删除这些行:

    #if not index.model().hasFlag(index, Qt.ItemIsEditable):
    check_box_style_option.state |= QtGui.QStyle.State_ReadOnly

    check_box_style_option.state |= QtGui.QStyle.State_Enabled

那应该解决它。

于 2014-12-18T14:42:44.150 回答