Reputation: 851
I am trying to display the value of a Boolean variable using a QCheckBox
widget, and render the user unable to change the displayed value. I don't want to disable it, as the resulting graying doesn't look good. I have tried to approximate the effect by changing the new value back to its previous value when the user clicks the QCheckBox
. However, the problem is compounded by the fact that the state of the widget is described by the "checked" properties of the QAbstractButton
parent class, and the "state" properties of the QCheckBox
class itself. This gives rise to a combinatorial exercise of signals and slots, of which I have been unable to obtain any good result.
var_ctrl = QtGui.QCheckBox( 'some name' )
def rdslot1(state):
if state == QtCore.Qt.Checked:
var_ctrl.setCheckState( QtCore.Qt.Unchecked )
else:
var_ctrl.setCheckState( QtCore.Qt.Checked )
def rdslot2(state):
if var_ctrl.isChecked():
var_ctrl.setChecked(False)
else:
var_ctrl.setChecked(True)
# Signal/Slot combinations (only one should be active)
var_ctrl.stateChanged.connect( rdslot1 )
var_ctrl.toggled.connect( rdslot2 )
var_ctrl.stateChanged.connect( rdslot2 )
var_ctrl.toggled.connect( rdslot1 )
Upvotes: 4
Views: 9088
Reputation: 105
Make Another QLable on top of QCheckBox based on condition, it will stop checbox under it to be checked on unchecked.
Upvotes: 0
Reputation: 4022
I'm late to the party - it seems like you got a solution that works. For future reference tho, another way you can do it would be to consume the mouse events - which keeps all of your signals working the way they should:
from PyQt4 import QtGui, QtCore
class MyCheckBox(QtGui.QCheckBox):
def __init__( self, *args ):
super(MyCheckBox, self).__init__(*args) # will fail if passing **kwargs
self._readOnly = False
def isReadOnly( self ):
return self._readOnly
def mousePressEvent( self, event ):
if ( self.isReadOnly() ):
event.accept()
else:
super(MyCheckBox, self).mousePressEvent(event)
def mouseMoveEvent( self, event ):
if ( self.isReadOnly() ):
event.accept()
else:
super(MyCheckBox, self).mouseMoveEvent(event)
def mouseReleaseEvent( self, event ):
if ( self.isReadOnly() ):
event.accept()
else:
super(MyCheckBox, self).mouseReleaseEvent(event)
# Handle event in which the widget has focus and the spacebar is pressed.
def keyPressEvent( self, event ):
if ( self.isReadOnly() ):
event.accept()
else:
super(MyCheckBox, self).keyPressEvent(event)
@QtCore.pyqtSlot(bool)
def setReadOnly( self, state ):
self._readOnly = state
readOnly = QtCore.pyqtProperty(bool, isReadOnly, setReadOnly)
Setting the code up this way gets you a few things (which you may or may not care about) but can be useful when developing custom Qt widgets:
Upvotes: 4
Reputation: 59664
Try to disable the checkbox widget, but override its look using widget palette or style
Upvotes: 1
Reputation: 851
Well later on I came up with a shortcut, which simply catches the clicks of the user and handles them according to a specifiable 'Modifiable' property. I have made this class:
class MyQCheckBox(QtGui.QCheckBox):
def __init__(self, *args, **kwargs):
QtGui.QCheckBox.__init__(self, *args, **kwargs)
self.is_modifiable = True
self.clicked.connect( self.value_change_slot )
def value_change_slot(self):
if self.isChecked():
self.setChecked(self.is_modifiable)
else:
self.setChecked(not self.is_modifiable)
def setModifiable(self, flag):
self.is_modifiable = flag
def isModifiable(self):
return self.is_modifiable
It behaves just like a normal QCheckBox
, being modifiable by default. However, when you call setModifiable(False)
, everytime you click it, it keeps the current state of the widget. The trick was to catch the clicked
signal, not toggled
neither stateChanged
.
Upvotes: 1