How to set read-only checkbox in PySide / PyQt

I am trying to display the value of a boolean variable using the QCheckBox widget and render a user who cannot change the displayed value. I do not want to turn it off, as the result of graying does not look good. I tried to approximate the effect by changing the new value to the previous value when the user clicks the QCheckBox button. However, the problem is compounded by the fact that the state of the widget is described by the "verified" properties of the parent class QAbstractButton and the "state" properties of the QCheckBox class QCheckBox . This leads to the combinatorial implementation of signals and slots, from which I could not get a 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 ) 
+4
source share
3 answers

I'm late to the party - it looks like you have a solution that works. For future reference, another way you can do this is to use mouse events that save all your signals in 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 up the code this way gives you a few things (which you may or may not need to take care of), but can be useful when developing your own Qt widgets:

  • Event consumption blocks signal emission, so you can connect other slots to things like clicking and switching. If you are looking for these signals, and then just toggle the value on / off, then other widgets that listen to these signals will not start correctly.
  • Using isReadOnly / setReadOnly supports a class that matches the Qt style
  • Creating pyqtSignals and pyqtSlots will help if you open the plugin for Qt Designer
+4
source

Well, later I came up with a shortcut that simply catches user clicks and processes them according to a specific “Modifiable” property. I 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 like a regular QCheckBox , being modifiable by default. However, when you call setModifiable(False) , every time you click on it, it saves the current state of the widget. The trick was to catch a clicked signal, not toggled nor stateChanged .

+1
source

Try disabling the checkbox widget, but redefine its appearance using the palette or style widget

+1
source

All Articles