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
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.