Traduzione a cura di Fabrizio Angius [qtsolutions -A-T- gmx.net]
English TOC.
Qt e' conosciuto soprattutto come un toolkit cross-platform per interfacce utente, ma e' molto di piu'. Qt supporta, oltre alle interfacce grafiche, anche database, file, filesystem, socket e molto altro, indipendentemente dalla piattaforma. Questo porta ad avere sia vantaggi che svantaggi: non e' necessario avere miliardi di librerie per ogni applicazione, ma il prezzo da pagare e' una libreria molto grande.
Qt e' scritto in C++, ma ci sono binding per molti altri linguaggi, come C, Python, C#, ecc. E' completamente orientato agli oggetti e' puo' essere considerato event-driven.
Qt estende inoltre il C++ con segnali e slot utilizzando il moc, meta object compiler. Questo permette la creazione di componenti collegati tra loro in modo molto leggero e che possono essere cosi' facilmente riutilizzati.
In questo capitolo introduttivo creeremo un'applicazione molto semplice che dimostri l'aspetto e il comportamento di Qt, il tutto seguendo il codice. In questo capitolo tutto il codice e' scritto da zero, ma (ovviamente) esiste un ambiente di sviluppo integrato che vi permette di 'disegnare' le interfacce utente. Questo viene discusso nel capitolo cinque e seguenti. L'immagine 1-1 mostra uno screenshot dell'applicazione.
Iniziate creando una nuova cartella per contenere i file dell'applicazione. Io la chiamo ex01, ma e' solo una convenzione che usero' per gli esempi di questo libro.
Un'intefaccia utente grafica, GUI, e' composta da 'widget' (o 'controlli' come vengono chiamati in win32). Questi widget possono essere composti da altri widget e in questo caso vengono chiamati, appunto, widget composti, oppure possono essere widget semplici, come un pulsante, un'area di testo o qualsiasi altra cosa possiate trovare in un'applicazione. Inizieremo dichiarando il nostro widget composto personale.
Create il file mywidget.h nella cartella che avete creato poco fa, quindi inserite nel file il codice dell'esempio 1-1.
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <qvbox.h>
class MyWidget : public QVBox
{
Q_OBJECT
public:
MyWidget( QWidget *parent = 0, char *name = 0 );
};
#endif
Questo codice sembrera' piuttosto normale a chiunque sia abituato al C++. Quello che facciamo e' ereditare la classe QVBox, che e' semplicemente un widget usato per contenere altri widget da allineare verticalmente (da qui la V nel nome). Questo significa che ogni ogni widget che inseriamo in questo verra' ordinato verticalmente, dall'alto verso il basso. I parametri del costruttore, parent e name, vengono passati alla superclasse fino ad incontrare QObject. Questo viene fatto per gestire la memoria e per semplificare il debugging dell'applicazione risultante. La macro Q_OBJECT fa delle meravigliose magie, come abilitare segnali e slot. Ulteriori informazioni si possono trovare nella documentazione della Trolltech e piu' avanti in questo tutorial.
Passiamo ora all'implementazione. Create un nuovo file: mywidget.cpp e salvatelo nella stessa cartella di mywidget.h. Inseriteci il codice dell'esempio 1-2.
#include <qlcdnumber.h>
#include <qslider.h>
#include "mywidget.h"
MyWidget::MyWidget( QWidget *parent, char *name ) : QVBox( parent, name )
{
QLCDNumber *lcd = new QLCDNumber( this );
QSlider *s = new QSlider( QSlider::Horizontal, this );
connect( s, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)) );
}
Gli include all'inizio servono per le due classi Qt che usiamo: QLCDNumber e QSlider. La parte interessante e' nel costruttore. Prima, chiamiamo il costruttore di QVBox per passare 'parent' e 'name' a tutte le superclassi fino a incontrare eventualmente QObject, che e' la superclasse di (quasi) tutte le classi Qt. Nel corpo del costruttore istanziamo un display LCD e uno slider. Diciamo loro che il parent e' 'this', ossia li inseriamo nel nostro widget che li visualizzera' dall'alto verso il basso, cioe' il display LCD sopra allo slider. Passiamo ora all'azione per segnali slot. Connettiamo il segnale valueChanged(int) dello slider allo slot display(int) del display LCD.
La maggior parte dei programmatori C++ obietteranno vedendo questo codice: facciamo una new, ma nessuna delete. Questa viene gestita dalla superclasse da cui i nostri widget derivano. Attraverso QVBox (e qualche altra classe) ereditiamo la classe QObject, che si preoccupa di eseguire la delete sui suoi figli quando si esegue la delete su di essa. In questo modo, quando il nostro widget verra' cancellato, verranno cancellati automaticamente anche il display LCD e lo slider.
Per concludere, creiamo un file main.cpp nella solita cartella e ci mettiamo il misterioso main mostrato nell'esempio 1-3.
#include <qapplication.h>
#include "mywidget.h"
int main( int argc, char **argv )
{
QApplication a( argc, argv );
MyWidget *w = new MyWidget();
a.setMainWidget( w );
w->show();
return a.exec();
}
Prima creiamo una QApplication. Questo puo' essere fatto solo una volta in tutto il processo e ci permette di avere un contesto in cui lavorare. Quindi istanziamo il nostro widget, lo impostiamo come il widget principale dell'applicazione e lo mostriamo. L'ultima cosa che facciamo e' chiamare il metodo exec() dell'applicazione. Questo metodo gestisce il ciclo degli eventi e crea l'evento nello slider, che poi emette il segnale che noi abbiamo collegato al display LCD; in questo modo abbiamo un'applicazione funzionante.
Per compilare il tutto, dobbiamo eseguire il moc sul widget, quindi compilare i file prodotti ed eseguire il link di tutto. Questo e' tutto molto semplice grazie a qmake. Basta digitare qmake -project && qmake && make nella console e poi eseguire l'applicazione. Verra' fatto tutto automaticamente. Se incontrate dei problemi durante la compilazione, date un'occhiata al capitolo tre e alle numerose informazioni reperibili su internet.
Ora, per concludere, mi permettero' di diventare un po' filosofico. Prima, in questo capitolo, ho parlato di 'programmazione modulare'. Notate che lo slider non sa che sta cambiando i valori di un display LCD. In effetti non sa che sta cambiando qualcosa, esso emette semplicemente un segnale. Allo stesso modo, il display LCD non sa cosa sta chiamando il metodo display. Potrebbe trattarsi di codice normalissimo oppure di un segnale. Entrambi sono collegati in modo molto leggero. Cio' migliora notevolmente la modularizzazione dei widget e quindi rende piu' facile un loro futuro riuso.
Qui potete trovare il codice sorgente per questo capitolo.
This is a part of digitalfanatics.org and is valid XHTML.
Copyright (c) 2002-2004 by Johan Thelin (e8johan -at- digitalfanatics.org). This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 (local copy) or later (the latest version is presently available at http://www.opencontent.org/openpub/). Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.