2013-04-02 11 views
7

Ho ricevuto una classe derivata da QWidget che contiene tre QSpinBox (ad esempio coordinate). Il segnale valueChanged() è collegato e viene emesso in almeno questi tre casi:Qual è il modo giusto per sopprimere i segnali Qt quando i valori sono impostati in modo esplicito

  1. su/giù tasto
  2. inseriti manualmente il numero
  3. setValue()

Tuttavia, quando si utilizza setValue(), voglio sopprimere il segnale (s), dal momento che non voglio avere (tre) segnali. Nella mia comprensione, ci sono due modi per farlo:

  1. QObject::blockSignals()
  2. utilizzando un flag che indica se i valori sono stati esplicitamente impostati

entrambe le varianti di lavoro, ma penso che non sono diritti -In avanti affatto: Per il primo, generalmente blocco tutti i segnali E ho bisogno di impostare blockSignals(true) per tutti i widget underyling (blockSignals non blocca i bambini QObjects nella mia applicazione). Per il secondo, ho bisogno di interrogare il flag in ogni metodo di aggiornamento E i segnali vengono sollevati anche se non ne ho bisogno.

Esistono schemi di progettazione generali che impediscono tale comportamento? In caso contrario, quale variante preferiresti?

risposta

4

La terza opzione sarebbe quella di sottoclasse QSpinBox, implementare la funzionalità desiderata e utilizzare la classe derivata invece di QSpinBox - questo nasconde tutta la complessità associata nella classe derivata e consente di utilizzarlo come QSpinBox.

Ad esempio seguente classe

myQSpinBox.h

#ifndef MYQSPINBOX_H 
#define MYQSPINBOX_H 

#include <QSpinBox> 

class myQSpinBox : public QSpinBox 
{ 
    Q_OBJECT 
public: 
    myQSpinBox(QWidget * parent = 0); 
protected: 
    bool valueBeingSet; 
public slots: 
    void setValue (int val); 
private slots: 
    void On_valueChanged(int val); 
signals: 
    void valueChangedNotBySet(int val); 
}; 

#endif // MYQSPINBOX_H 

myQSpinBox.cpp

#include "myQSpinBox.h" 

myQSpinBox::myQSpinBox(QWidget * parent) 
     : QSpinBox(parent) 
     , valueBeingSet(false) 
{ 
    connect(this,SIGNAL(valueChanged(int)),this,SLOT(On_valueChanged(int))); 
} 

void myQSpinBox::setValue (int val) 
{ 
    valueBeingSet = true; 
    QSpinBox::setValue(val); 
    valueBeingSet = false; 
} 

void myQSpinBox::On_valueChanged(int val) 
{ 
    if(!valueBeingSet) 
     emit valueChangedNotBySet(val); 
} 

emetterà valueChangedNotBySet(int); nei casi 1. e 2., ma non nel caso 3. , mantenendo intatte tutte le funzionalità di QSpinBox

+0

Hey Ilya, grazie. Hai assolutamente ragione - questa è la terza (e finora più pulita) variante. Tuttavia, avrei bisogno di reimplementare (una volta) tutti i tipi di widget (il QSpinBox era solo un esempio) - QLineEdit, QComboBox, QDoubleSpinBox, .... – braggPeaks

+0

Non sono sicuro se QLineEdit debba essere reimplementato - poiché QLineEdit ha segnali textChanged (const QString e testo) e textEdited (const QString e testo) che consentono di distinguere tra i tipi di modifiche. Lo stesso potrebbe valere per QComboBox ... –

+1

Funzionerebbe solo quando tutto accade nel thread dell'interfaccia utente. Quando si hanno catene di connessione segnale/slot su più thread, 'valueBeingSet' sarà impostato su' false' prima che il segnale 'valueChnaged 'venga emesso di nuovo (infinitamente), perché il gestore di eventi verrà chiamato in modo asincrono. – fferri