L'intero meccanismo di
meta object system è stato inventato dai programmatori (detti anche Troll, richiamando le antiche figure della mitologia norvegese a cui si attribuivano poteri magici) di Trolltech, ora divenuta Nokia, per consentire agli utenti del toolkit di scrivere il proprio codice sorgente, senza doversi perdere nei dettagli del sistema operativo sottostante.
Il
punto cruciale, a cui i Troll dovevano trovare soluzione, era quello di far comunicare tra loro gli oggetti C++ della libreria, senza per questo dover dipendere dai metodi di comunicazione nativi, quali ad esempio la gestione degli eventi di Windows o di X11, in modo da rimanere indipendenti dall'implementazione.
Prima di addentrarci nell'analisi del meccanismo di comunicazione adottato da Qt - chiamato
Signals&Slots - cerchiamo di capire in cosa consiste il problema: supponiamo di avere una finestra di dialogo contenente due oggetti grafici molto semplici, un bottone e un indicatore visivo (immaginiamo, a titolo di esempio, qualcosa di simile alla lampada di un semaforo, di colore rosso); supponiamo inoltre di voler dotare la nostra finestra di una semplice funzionalità, al clic del mouse sul bottone grafico, il colore del nostro semaforo diventi verde.
Il semplice esempio sopra riportato, ci pone di fronte al problema di far comunicare tra loro i nostri due oggetti grafici: il pulsante e il semaforo; in altre parole, quando il pulsante viene premuto, deve essere emesso un "segnale" al semaforo, in modo che esso possa riconoscere l'evento e cambiare colore.
In estrema sintesi, il nostro problema di comunicazione può essere descritto con le parole di "segnale", corrispondente all'evento di bottone premuto e "cambio colore", funzione propria dell'oggetto grafico semaforo, innescata dal segnale di bottone premuto: usando la terminologia Qt, questo è uno
slot. Allo stato attuale delle cose, abbiamo identificato un segnale e uno slot, ciò che ancora ci manca è un metodo per il loro collegamento. Il meccanismo di
meta object system di Qt offre una funzione (
connect), indipendente dalla piattaforma, per realizzare questa connessione.
I
signal sono i segnali emessi dai widget Qt a fronte di eventi (interni o esterni), mentre gli
slot sono praticamente identici alle funzioni membro di una classe; si può quindi parlare di slot pubblici, privati e protetti secondo l'accezione classica del linguaggio C++, e possono essere invocati così come avviene per tutti gli altri metodi tradizionali di una classe.
La differenza sostanziale è che uno slot può sempre essere collegato a un segnale e quindi sarà invocato ogni volta che il segnale verrà emesso. Questo collegamento signal/slot, viene realizzato con la funzione di libreria
connect e ha la sintassi:
connect(sender,SIGNAL(signal),receiver,SLOT(slot));
dove
sender e
receiver sono i puntatori agli oggetti Qt - nel nostro esempio
sender è il bottone e
receiver il semaforo - da porre in comunicazione e signal, slot sono funzioni (in questo caso senza parametri) appartenenti rispettivamente all'oggetto
sender e
receiver.
Nel caso invece di collegamento signal/slot con un parametro intero si avrà:
connect(sender,SIGNAL(signal(int)),receiver,SLOT(slot(int)));
La macro
SIGNAL() e la macro
SLOT() sono essenziali per il funzionamento del tutto e verranno preprocessate dal
meta object compiler (moc) prima della compilazione di tutti i file del progetto.
Il
meta object system di Qt è quindi un passo di
pre-processing in grado di generare codice C++ puro, partendo dalla definizione degli oggetti Qt. In questo modo, il meccanismo
Signals&Slots, potrà funzionare su qualsiasi sistema operativo, l'unica condizione necessaria è quindi la disponibilità di un compilatore C++ standard (quale ad esempio gcc).
L'uso di
moc e qmake libera quindi il programmatore da tutti i dettagli di implementazione necessari al funzionamento multipiattaforma del meccanismo
Signals&Slots.
Così come esiste una funzione
connect, esiste anche la funzione opposta, la
disconnect, usata per disconnettere il segnale dallo slot precedentemente collegato. La
sintassi della funzione è:
disconnect(sender,SIGNAL(signal),receiver,SLOT(slot));
In questo modo è possibile attivare e disattivare il collegamento tra oggetti a runtime. Va inoltre ricordato che più segnali possono essere collegati a uno stesso slot, un segnale può essere collegato a più slot o a un altro segnale:
connect(sender,SIGNAL(signal1),receiver,SLOT(signal2));
In questo caso, quando viene emesso il segnale
signal1, verrà anche emesso il segnale
signal2.