2011-08-31 8 views
6

Si llamé a QCheckBox::setChecked(x), la señal toggled solo se emite si x no es el mismo que el estado actual de la casilla de verificación. Entiendo la lógica detrás de esto, para evitar señalar si nada ha cambiado. Sin embargo, en algunas situaciones en las que tengo una configuración de widgets más complicada, necesito que la señal se emita siempre. Esto garantiza que cualquier persona que se haya conectado a la casilla de verificación recibirá el primer estado.Qt fuerza QCheckBox para emitir señal en setChecked

¿Hay alguna manera de que QCheckBox::setChecked(bool) emita una señal independientemente de si el estado ha cambiado?


Mi solución simple ahora es simplemente forzar la casilla de verificación en varios estados haciendo setChecked(!x) y setChecked(x). Esperaba una forma más correcta de hacer esto.

Respuesta

0

Una forma sería a la subclase QCheckBox y poner en práctica la emisora ​​de señales en que, cuando lo necesite, por ejemplo:

class MyCheckBox : public QCheckBox 
{ 
    Q_OBJECT 
public: 
    MyCheckBox(QWidget *parent = 0) : QCheckBox(parent) {}; 

    virtual void setChecked(bool checked) { 
      QCheckBox::setChecked(checked); emit checkWasSet(checked); 
      }; 
signals: 
    void checkWasSet(bool value); 

}; 

Ahora utilizar esta clase en lugar de la clase QCheckBox regular, y se puede conectar a la señal checkWasSet() para cada vez que se establece el estado de verificación.

+0

'setChecked' no es virtual en' QAbstractButton' (según la documentación).Además, quiero que el mecanismo sea genérico, de cualquier forma en que se establezca el estado. También tengo que repetir el patrón para varias otras clases (QCheckBox fue solo mi ejemplo aquí). –

6

Mirando en la implementación QAbstractButton, me encontré con las siguientes líneas de código:

if (!d->checkable || d->checked == checked) { 
    if (!d->blockRefresh) 
     checkStateSet(); 
    return; 
} 

donde checkStateSet es una función virtual. QCheckBox anula esto y emite una señal stateChanged() solo si el estado ha cambiado. No he probado esto, pero creo que d->blockRefresh está configurado en false si llama directamente al QCheckBox::setChecked(...).

Si este es el caso, esto significa que usted podría subclase QCheckBox y reemplazar el método checkStateSet() a algo como esto:

void MyCheckBox::checkStateSet() 
{ 
    QCheckBox::checkStateSet(); 
    if(m_oldState == checkState()) 
    { 
     // emit the signal here, as QCheckBox::checkStateSet() didn't do it. 
     emit stateChanged(m_oldState); 
    } 
    else 
    { 
     // don't emit the signal as it has been emitted already, 
     // but save the old state 
     m_oldState = checkState(); 
    } 
} 

donde el archivo de cabecera contiene

private: 
    Qt::CheckState m_oldState; 

que debe ser inicializado a Qt::Unchecked en el constructor.

+0

Esto podría funcionar, pero tener que crear una subclase por este motivo es un poco problemático: debe recordar en el diseñador para promocionar, y todos los programadores deben recordar usar esta clase en su lugar. –

2

Aquí hay otra solución que puede o no puede ser posible para su caso:

Si usted puede estar 100% seguro de que sus señales y las ranuras están conectados antes de la casilla de verificación tiene la oportunidad de cambiar su estado, cada conectados la clase puede inicializarse de manera segura asumiendo que la casilla de verificación no está marcada. Esto se debe a que las casillas de verificación siempre se desmarcan al momento de la construcción. De esta manera es posible que no tenga que llamar al setChecked() después de conectar las señales.

Sin embargo, este enfoque no funciona si existe la posibilidad de que se conecte una señal después de que la casilla de verificación ya haya cambiado. No soy 100% aficionado a este enfoque, pero podría ser una opción para ti.

0

Usted podría emitir la señal con el estado actual de sí mismo:

checkbox.stateChanged.emit(checkbox.checkState()) 
Cuestiones relacionadas