disabled qtablewidgetitem is not shown gray

3.8k Views Asked by At

i have a qtablewidgetitem and inside it there is a QCheckbox

when disabling qtablewigetitem as follow

    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)

it is disabled and i can't click on it but it is dispalyed as it stills enabled.

i want to display it colored in gray

UPDATE:

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

and here is how i put it inside the QTableWidgetItem

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

There are 1 best solutions below

6
On BEST ANSWER

Use ^ instead.

flags ^= QtCore.Qt.ItemIsEnabled

| is the bitwise-OR. What it does is turns the enabled flag ON regardless of its original state. ^ will toggle it.

If you want to TURN OFF the flag REGARDLESS of its original state, just AND (&) it with its COMPLIMENT (~) like so:

flags = flags & ~QtCore.Qt.ItemIsEnabled

You can apply these principles of any flags that you want to turn off or on, like QtCore.Qt.ItemIsSelectable etc.

In your case, the code would be something like:

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)

Check out this for more details: https://wiki.python.org/moin/BitwiseOperators

Another wonderful answer that touches on this topic (very useful): How to find specific Qt.ItemFlag occurrence into custom Qt.ItemFlags instance in PyQt?

UPDATE-1: If your cells have items in the form of Widgets (egs. QCheckBox), you might want to approach it differently. You might want to disable the corresponding widget instead. So in your case you would do something like:

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

UPDATE-2: Since, you have now updated your question with more code, here's another update: In your paint method you have to apply the same bitwise operation principles as illustrated in the first part of this answer. So you would have to do something like:

    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

.. and REMOVE these lines:

    #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

That should fix it.