2009-05-10 10 views
11

Sono relativamente nuovo alla programmazione con Qt e ho avuto una domanda. Versione breve:Qt signals & inheritance question

Come si ereditano i segnali definiti nelle superclassi?

Sto cercando di creare una sottoclasse di qualcun altro QTWidgets ben fatti per cambiare alcuni dei comportamento di default:

 

//Plot3D is a QWidget that defines a signal "rotationChanged" 
class matLinePlot : public QObject, public Plot3D { 

    Q_OBJECT; 
     //etc... 
public: 
     //etc... 

     //Catch Plot3D's signal "rotationChanged" and do some magic with it: 
    void initPlot(){ 
       QObject::connect(this, SIGNAL(rotationChanged(double , double , double)), 
      this, SLOT(myRotationChanged(double, double, double))); 
    } 
}; 

Il problema è nel QObject :: collega la linea. Quello che mi piacerebbe fare è collegare il SIGNAL rotationChanged (da qwt3D_plot.h) a una funzione locale/SLOT - "myRotationChanged". Tuttavia ogni volta che lo faccio, in fase di esecuzione ottengo:

Object::connect: No such signal matLinePlot::rotationChanged(double, double, double)

in C: ... \ matrixVisualization.h. Naturalmente, so che rotationChanged non è in matrixVisualization.h - è in qwt_plot3D.h, ma ho pensato che dal momento che erediti da Plot3D tutto dovrebbe andare bene. Ma, ora che ci penso, dal momento che SIGNAL e SLOT sono macro, suppongo che lo MOC non sappia/si preoccupi dell'ereditarietà.

Il che mi porta alla mia domanda - dal momento che MOC e SEGNALAZIONI/SLOT non sembrano sapere sull'eredità ecc. Come posso creare una sottoclasse di un widget definito da qualche altra parte e ottenere l'accesso ai segnali del widget?

Ho un sacco di esempi su come utilizzare l'incapsulamento per realizzare qualcosa di simile, ma temo di non capire come farlo con l'ereditarietà.

Scusate se questa è una domanda ridicola - mi sento come se mi mancasse qualcosa di ovvio.

+1

il riferimento che si vede nell'errore a "matrixVisualization.h" mostra in quale file è fallito QObject :: connect, non dove sta cercando di "cercare" il segnale corrispondente. –

risposta

9

Credo che il problema è l'ereditarietà multipla:

class matLinePlot : public QObject, public Plot3D 
... 

presumo che Plot3D è un sottoclasse di QObject? In questo caso, si dovrebbe fare

class matLinePlot : public Plot3D 
... 

invece.

+1

Questo rende le cose in un errore di collegamento: 1> moc_matrixVisualization.obj: errore LNK2001: simbolo esterno "public: static struct QMetaObject const qwt3d :: :: tracciare3d staticMetaObject"? (StaticMetaObject @ @ tracciare3d qwt3d @@ @@ 2UQMetaObject B) Il documento QT suggerisce l'utilizzo dell'ereditarietà multipla: http://doc.trolltech.com/4.3/uitools-multipleinheritance.html Anche se estendono QWIdget, ho bisogno di QObject. – Pete

+2

Il link che hai postato mostra un esempio su come usare i file .ui (quei file creati da Qt Designer). Una differenza importante è che Ui :: CalculatorForm non è una sottoclasse di QObject. La regola quando la sottoclasse da QObject (e l'utilizzo dell'ereditarietà multipla) è che solo una delle superclassi può essere un QObject e che QObject deve essere la prima parte nell'ereditarietà. – ashcatch

+1

il documento suggerisce l'ereditarietà multipla in uno scenario differente. quando usi Qt Designer otterrai un file .ui, quindi uno strumento chiamato uic prenderà il file .ui e genererà una classe che è fondamentalmente una traduzione del file .ui, solo nell'effettivo C++. quindi quello che stanno sostanzialmente suggerendo è di ereditare da quella classe, invece di averla come membro. –

1

Credo che funzionerà se il segnale Plot3D :: rotationChanged è pubblico o protetto. Sei sicuro che il segnale non sia privato?

Edit:

Anche se non sono riuscito a trovare un riferimento specifico, dovrò concludere che i segnali sono sempre pubbliche. Almeno un test che ho fatto qui sembrava indicare che potevo connettermi a un segnale anche se era stato dichiarato nella sezione privata di una classe.

Ho anche verificato che un segnale dichiarato in QObject potrebbe essere collegato utilizzando una sottoclasse di QObject nell'istruzione connect in modo che i segnali siano sicuramente ereditabili. Come vedo in altre risposte e commenti qui, il problema deve essere altrove.

+0

Ciao, Ho provato a mettere una parola chiave pubblica prima della parola chiave segnale, ma Qt MOC non ha fatto così: 1> MOC include \ qwt3d_plot.h 1> include \ qwt3d_plot.h (143): Errore: i segnali non possono avere identificatore di accesso 1> Progetto: errore PRJ0019: Uno strumento ha restituito un codice di errore da "MOC include \ qwt3d_plot.h" – Pete

+0

Oops. Ovviamente avrei dovuto usare "pubblico: segnali:", ma questo non ha aiutato. – Pete

0

Errato -> vedere i commenti.

Sto usando Qtopia in Uni e credo di ricordare qualcuno che dice qualcosa sulla spaziatura nei parametri SIGNAL e SLOT per la connessione.

provare a utilizzare

QObject::connect(this, SIGNAL(rotationChanged(double,double,double)), 
      this, SLOT(myRotationChanged(double,double,double))); 

Lo so che non sembra intuitivo, come C++ non è sensibile a spazi bianchi, ma credo che abbia qualcosa a che fare con un po 'della magia che Qtopia/QT usa quando collegamento di segnali e slot. Questo può valere solo per Qtopia, o forse ho sentito male, ma provalo. Inoltre i segnali sono pubblici o protetti e hai incluso i file di intestazione appropriati?

+0

Ora ho: pubblico: segnali: \t \t //! Emesso, se la rotazione viene modificata void rotationChanged (double xAngle, double yAngle, double zAngle); nell'intestazione e la biblioteca tramando, e QObject :: connect (questo, SIGNAL (rotationChanged (doppia, matrimoniale, doppia)), \t \t questo, SLOT (myRotationChanged (doppia, matrimoniale, doppia))); Nella mia classe derivata ... ancora lo stesso errore. Ho incluso l'intestazione: #include // ha classe Plot3D – Pete

+0

Quando dichiari i segnali, non dichiarare un nome per il parametro, solo i tipi. Questo è pubblico: segnali: void rotationChanged (double, double, double); Speriamo che questo risolva il tuo errore. – mdec

+0

La spaziatura non influisce sui segnali e sugli slot, ciò che hai sentito è la normalizzazione del segnale/slot che solo un po 'di velocità accelera il codice, ma che comunque non è quasi notabile. – ismail

2

SIGNAL (x) e SLOT (x) sono macro che generano stringhe letterali. Durante il runtime, gli slot e i segnali vengono confrontati utilizzando i confronti tra stringhe di quei letterali generati.

(avrei aggiunto un commento al commento di MDEC, ma non ho abbastanza rep)

+0

Giusto - Penso che sia il cuore di questo problema; poiché la combinazione di stringhe MACRO/MOC cerca solo il file di intestazione corrente per il segnale, non sa di guardare nella mia altra libreria di codice compilato. – Pete

+0

Pete, sono abbastanza sicuro che ti sbagli. I segnali e gli slot sono tenuti da qualche parte (moc genera il codice per questo, puoi vederlo nel file * _moc), non ha nulla a che fare con il file di intestazione corrente. –

+0

(curses! - Non ho abbastanza rep per aggiungere l'ultimo commento di Pete sull'errore di collegamento) Sembra che tu non stia collegando in moc_qwt3D_plot.cpp. –