Immagine Ing. Giovanni Venturi - http://www.kde-it.org/ - Roma - Linux Day 2007 1/ Ing. Giovanni Venturi Roma, 27 ottobre 2007 - Linux Day rilasciato con Creative Commons Attribuzione-Non commerciale-condividi allo stesso modo 2.5 Italia License
2/
3/ Cosa sono le Qt?
4/ Cosa sono le Qt? Le librerie Qt sono una struttura multipiattaforma e completa per lo sviluppo di applicazioni in C+ +. Costituiscono la componente base su cui si poggia KDE per la realizzazione di pulsanti e finestre. Sono sviluppate dalla Trolltech, azienda Norvegese che ha stretto un accordo con KDE per permetterne l'uso anche se le Qt non erano rilasciate ancora con licenza GPL: www.trolltech.com. Il 30 ottobre 2000 la Trolltech rilascia le Qt 2.2 anche con licenza GPL.
5/ Perché dovrei usare le Qt?
6/ Perché dovrei usare le Qt? Perché le Qt sono librerie multipiattaforma disponibili per: GNU/Linux; FreeBSD, OpenBSD, NetBSD; Windows (sia per XP che per Vista); Mac Os X; per UNIX vari; Si riduce il costo per lo sviluppo essendo il codice utilizzabile nell'immediato sulle diverse piattaforme. Utilizza la potenza del C++ con un elevato numero di API e librerie già pronte per ogni esigenza.
7/ E Java?
8/ E Java? Molto spesso quando si parla di linguaggio multipiattaforma subito si pensa a Java della Sun Microsystem. Le Qt sono ora disponibili anche per: Java Standard Edition 5.0 Java Enterprise Edition 5.0 tramite QtJambi che permette di usare Java sfruttando i vantaggi delle caratteristiche delle Qt. Per informazioni: http://dot.kde.org/1154086784/ http://doc.trolltech.com/qtjambi-1.0/qtjambi-index.html
9/ Via coi preparativi
10/ Qt 4.4
11/ Qt 4.4 La versione di queste librerie è ancora in sviluppo, ma si promette: Supporto alla multimedialità (tramite Phonon di KDE 4) WebKit (per il rendering di pagine HTML come widget) Funzionamento su PDA con Windows CE e molto altro Qt 5 Non ci sono progetti per questa versione. Le Qt 4.x saranno a lungo sul mercato e permetteranno grandi evoluzioni.
12/ Innanzitutto...... bisogna procurarsi le librerie Qt e compilarle. Utilizzeremo le qt-copy dall'svn di KDE con le patch per KDE. La presenza di DBUS nel sistema su cui si installa Qt permetterà di comprendere anche il modulo QtDBus. export QTDIR=~/qt-copy export PATH=$QTDIR/bin:$PATH export QMAKESPEC=linux-g++ export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH cd svn co svn://anonsvn.kde.org/home/kde/trunk/qt-copy cd $QTDIR./apply_patches./configure -qt-gif -no-exceptions -debug -fast -prefix $QTDIR -confirmlicense make
13/ Documentazione Una volta compilate le librerie, saranno disponibili all'uso per la creazione della nostra prima applicazione. La cosa interessante per chi non le ha mai utilizzate è che sono ben documentate, infatti proprio nei file scaricati da SVN (come anche dai sorgenti scaricabili dal sito della Trolltech) troveremo la documentazione completa i HTML nella directory ~/qt-copy/doc/html I file di SVN trunk sono relativi alla versione 4.3.2 di Qt. In tale documentazione c'è la descrizione di tutti i metodi utilizzabili in tutte le classi C++ di Qt, con in più tanti esempi e tutorial per imparare.
14/ Qt assistant
15/ Qt assistant La documentazione sulle Qt è davvero tanta. Ci sono informazioni complete su: membri signal slot disponibili per ogni singola classe di Qt. Vi sono molti esempi di programmazione Qt, tutorial vari su argomenti avanzati (SQL, Thread,...) e tanto altro. In più vi è il Qt assistant che è una applicazione che permette di ricercare la documentazione richiesta, stamparla, accedere alle sottosezioni varie: designer, linguistic e qmake.
16/ Un primo esempio
17/ Un primo esempio main.cpp... #include <QApplication> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc, argv); } QPushButton hello("hello world!"); hello.resize(100, 30); hello.show(); return app.exec();
18/ Il codice gli #include... #include <QApplication> include la definizione della classe QApplication. Ogni GUI ha un solo oggetto di tipo QApplication che gestisce varie risorse come font e cursore predefiniti #include <QPushButton> include la definizione della classe QPushButton che è usata per definire nella GUI un pulsante che l'utente può premere e rilasciare. La classe ne gestisce l'aspetto come per ogni QWidget. Un elemento di QPushButton può mostrare sia testo che icone (classe QIcon).
19/ Il codice il main... int main(int argc, char *argv[]) QApplication app(argc, argv); elementi istanzia la GUI per poter aggiungere i vari QPushButton hello("hello world!"); crea il pulsante con del testo hello.resize(100, 30); ridimensiona lo stesso hello.show(); rende visbile la GUI (nessuna GUI creata lo è) return app.exec(); riceve e processa gli eventi di sistema e di utente legandoli agli appositi elementi della GUI
20/ Compiliamo ed eseguiamo il codice Creando main.cpp nella directory ld-01. Basta dare i comandi: qmake -project qmake Il primo crea il file ld-01.pro e il secondo il file Makefile. Per compilare il codice (main.cpp) si esegue il classico: make A questo punto./ld-01 esegue l'applicazione. Ma cosa succede? Perché il pulsante non reagisce ai clic? Non è stata definita una corrispondente azione per il clic.
21/ Secondo esempio
22/ Secondo esempio main.cpp... #include <QApplication> #include <QFont> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton quit("esci!"); quit.resize(75, 30); quit.setfont(qfont("courier", 18, QFont::Bold)); QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit())); } quit.show(); return app.exec();
23/ Il codice gli #include... Agli #include precedenti si aggiunge: #include <QFont> che aggiunge la definizione della classe QFont per poter cambiare il font usato nel testo del pulsante utilizzato quit.setfont(qfont("courier", 18, QFont::Bold)); è utilizzato per impostare il font Courier, con dimensione 18 in grassetto QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit())); serve per legare l'azione del clic con la corrispondente azione ti terminazione della GUI.
24/ Segnali e slot
Segnali e slot In ogni applicazioni GUI creata con Qt si utilizzerà il concetto di SIGNAL/SLOT ovvero gli oggetti Qt possono comunicare tra di loro per il verificarsi di eventi: il clic su un pulsante, la modifica del valore di un oggetto come uno slider Un oggetto emette un SIGNAL e un'altro oggetto lo intercetta eseguendo lo SLOT corrispondente. Tale corrispondenza nell'esempio precedente era stata definita dalla riga: QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit())); Ing. Giovanni Venturi - http://www.kde-it.org/ - Roma - Linux Day 2007 25/
26/ Schema SIGNAL/SLOT L'emissione del segnale signal1 per l'oggetto Object1 produce l'esecuzione dello slot slot1 nell'oggetto Object2 e dello slot slot2 nell'oggetto Object2 e così via... l'emissione può essere implicita o esplicita. Implicita se si verifica un evento che produce il segnale Esplicita se si invoca l'emissione del segnale tramite emit nomesegnale
27/ Alcune proprietà di SIGNAL/SLOT Per utilizzare un meccanismo di SIGNAL/SLOT la classe deve ereditare dalla classe QObject o da QWidget Classi come QPushButton, QLabel, QCheckBox, QRadioButton,... ereditano da dette classi, quindi tale meccanismo è già utilizzabile I parametri che si possono usare nei signal e negli slot per un oggetto personalizzato possono essere dei tipi desiderati e in un numero desiderato, naturalmente devo corrispondere Un signal può anche invocare un altro signal che a sua volta eseguirà lo slot corrispondente
28/ Esempio di SIGNAL/SLOT - parte 1 Ecco la dichiarazione di una classe minimale C++ senza il meccanismo del signal/slot: class Counter { public: Counter() { m_value = 0; } int value() const { return m_value; } void setvalue(int value); private: int m_value; }; Per usare signal/slot basta modificare...
29/ Esempio di SIGNAL/SLOT - parte 2 #include <QObject> class Counter : public QObject { Q_OBJECT public: Counter() { m_value = 0; } int value() const { return m_value; } public slots: void setvalue(int value); signals: void valuechanged(int newvalue); private: int m_value; }; Q_OBJECT serve per poter dichiare signal e slot e deve essere presente all'inizio, inoltre la classe deve ereditare da QObject public slots: dichiara gli slot pubblici della classe signals: dichiara i signal disponibili
30/ Esempio di SIGNAL/SLOT - parte 3 Ecco l'implementazione dello slot: void Counter::setValue(int value) { if (value!= m_value) { m_value = value; emit valuechanged(value); } } Ed ecco il codice che utilizzerà il meccanismo: Counter a, b; QObject::connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int))); a.setvalue(12); // a.value() == 12, b.value() == 12 b.setvalue(48); // a.value() == 12, b.value() == 48
31/ Esempio di SIGNAL/SLOT - parte 4 Ecco l'implementazione dello slot: void Counter::setValue(int value) { if (value!= m_value) { m_value = value; emit valuechanged(value); } } Ed ecco il codice che utilizzerà il meccanismo: Counter a, b; QObject::connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int))); Importante Si è aggiunta la condizione (value!= m_value) per evitare un ciclo infinito nel caso in cui si imposta anche la connessione: QObject::connect(&b, SIGNAL(valueChanged(int)), &a, SLOT(setValue(int))); a.setvalue(12); // a.value() == 12, b.value() == 12 b.setvalue(48); // a.value() == 12, b.value() == 48
32/ Qt designer
33/ Qt designer Quando si programma con Qt, si realizzano elementi grafici, quindi se per qualche motivo si desidera accellera il processo di scrittura del codice è possibile utilizzare uno strumento visuale che pemette di aggiungere gli elementi grafici con qualche clic. Tale strumento visuale è il Qt designer. Questo realizza un file con estenzione UI, che altro non è che un file XML che contiene la descrizione del form grafico realizzato.
34/ Come integrare nel codice il form del Qt designer?
35/ Integrazione nel codice del form realizzato con lo strumento Qt designer Dopo aver realizzato un form con il Qt designer viene naturale chiedersi come avvenga l'operazione di integrazione con del codice "complesso". Questa risposta è presente nella documentazione accessibile con il comodo Qt assistant (Using a Component in Your Application). Si possono usare tre metodi:. The Direct Approach. The Single Inheritance Approach. Automatic Connections Si analizza il caso semplice dell'approccio diretto. Per gli altri riferirsi all'esauriente documentazione.
36/ Approccio diretto
37/ Integrazione nel codice con approccio diretto Dopo aver realizzato un form con il Qt designer si integra il form in maniera molto semplice nel codice procedendo come segue. I sorgenti dell'applicazione consistono di due file: main.cpp e form.ui. Si scrive il file.pro come segue: TEMPLATE = app FORMS = form.ui SOURCES= main.cpp Il parametro FORMS dice a qmake quale file deve essere processato da uic. In questo caso il file form.ui è utilizzato per creare il file ui_form.h che può essere usato da qualunche file in SOURCES.
38/ Integrazione nel codice con approccio diretto Per essere certi che qmake genererà il file ui_form.h, bisogna includerlo in un file elencato in SOURCES. Dal momento che main.cpp è l'unico file allora lo si includerà lì avendo quindi: #include "ui_form.h" #include <QApplication> Con questo controllo aggiuntivo ci si assicura che non si genera del codice per i file.ui non utilizzati.
39/ Integrazione nel codice con approccio diretto La funzione principale crea la finestra di dialogo costruendo una classe QDialog standard che si usa per ospitare l'intercaccia utente descritta dal file form.ui. int main(int argc, char *argv[]) { QApplication app(argc, argv); QDialog *window = new QDialog; Ui::Dialog ui; ui.setupui(window); } window->show(); return app.exec();
40/ Integrazione nel codice con approccio diretto In questo caso, Ui::Dialog è un oggetto che descrive l'interfaccia relativa al file ui_form.h che imposta gli elementi grafici della finestra di dialogo e le connessioni tra i suoi signal e slot. Questo approccio fornisce un metodo veloce e semplice per usare semplici, componenti auto-contenuti nella propria applicazione, ma molti componenti creati con il Qt designer avranno bisogno di essere integrati in modo più stretto con il resto del codice dell'applicazione. Per ottenere ciò vediamo un brevissimo esempio.
41/ Esempio finale
42/ Personalizzazione codice creato con designer - form.pro: TEMPLATE = app HEADERS= newdialog.h FORMS = form.ui SOURCES= main.cpp newdialog.cpp - main.cpp: #include "newdialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication app(argc, argv); NewDialog *window = new NewDialog; } window->show(); return app.exec();
43/ Personalizzazione codice creato con designer:.h - newdialog.h: #include "ui_form.h" class NewDialog : public QDialog { Q_OBJECT public: NewDialog(QWidget *parent = 0); private: Ui::Dialog ui; public slots: void calculate(); };
44/ Personalizzazione codice creato con designer:.cpp - newdialog.cpp: #include "newdialog.h" NewDialog::NewDialog(QWidget *parent) : QDialog(parent) { ui.setupui(this); ui.value->setfocus(); ui.result->clear(); connect(ui.evalutebutton, SIGNAL(clicked()), this, SLOT(calculate())); } void NewDialog::calculate() { ui.result->settext( ui.value->text() + " * 10 = " + QString::number(ui.value->text().toUInt() * 10) ); }
45/ Personalizzazione codice creato con designer: form Esce dall'applicazione Cancella il valore base calcola il valore base X 10
46/ Curiosità?... Domande? Grazie a tutti per la vostra attenzione KDE Italia - www.kde-it.org