如何在PySide / PyQt中设置“只读复选框”

时间:2012-07-13 14:16:12

标签: python qt pyqt pyqt4 pyside

我试图使用QCheckBox窗口小部件显示布尔变量的值,并使用户无法更改显示的值。我不想禁用它,因为灰化效果不好。我尝试通过在用户点击QCheckBox时将新值更改回其先前值来估算效果。但是,由于QAbstractButton父类的“已检查”属性以及QCheckBox类本身的“状态”属性描述了窗口小部件的状态,因此问题更加复杂。这导致信号和插槽的组合运动,我无法获得任何好的结果。

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 )

3 个答案:

答案 0 :(得分:4)

我迟到了 - 看起来你有一个有效的解决方案。为了将来参考,你可以采用的另一种方法是使用鼠标事件 - 这样可以保持所有信号的工作方式:

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)

以这种方式设置代码会为您提供一些内容(您可能会或可能不会关心)但在开发自定义Qt小部件时非常有用:

  1. 使用该事件会阻止信号发射,因此您仍然可以将其他插槽连接到clicked&切换。如果您正在寻找这些信号,然后只是打开/关闭值 - 那么听取这些信号的其他小部件将被错误地触发
  2. 使用isReadOnly / setReadOnly使类遵循Qt编码样式
  3. 创建pyqtSignals&如果将插件公开给Qt的Designer
  4. ,pyqtSlots会有所帮助

答案 1 :(得分:1)

以后我想出了一个快捷方式,它只是捕获用户的点击并根据可指定的“可修改”属性处理它们。我做了这个课:

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

它的行为与普通QCheckBox一样,默认情况下可以修改。但是,当您调用setModifiable(False)时,每次单击它时,它都会保持窗口小部件的当前状态。诀窍是捕获clicked信号,而不是toggled stateChanged

答案 2 :(得分:1)

尝试禁用复选框小部件,但使用小部件palettestyle

覆盖其外观