QtCreator

di Andrea Zani, in Software,

La realtà non è solo Windows. Lo viluppo di un software che sia casereccio o abbia grande aspettative può scontrarsi anche con questa necessità: poter girare anche su altri sistemi operativi. Java in primis, ma anche da qualche tempo il Framework .NET che, grazie a Mono, può girare anche su Linux e Mac, cercano di risolvere questa necessità. Il metodo utilizzato è semplice: dopo la compilazione, creano un eseguibile in bytecode, un linguaggio intermedio, che una macchina virtuale permette di eseguire. Praticamente possiamo far eseguire qualsiasi programma compilato in bytecode su qualsiasi sistema operativo che possiede questa macchina virtuale. Il Framework .NET o Java mettono a disposizione un gran numero di classi per quasi tutte le esigenze che un programmatore può aver bisogno, in modo che il programmatore non si deve scervellare per cercare accessi diretti a funzioni del kernel. Questo porterebbe già un grave problema di interoperabilità visto che, ovviamente, una funzione, per esempio la lettura di un file, è presente in un kernel in un determinato modulo mentre in un altro sistema operativo può essere in tutt'altro posto o non essere nemmeno disponibile. Nel nostro programma abbiamo la necessità di leggere un file? Bene, in C# con il Framework .NET scriviamo:

string content = System.IO.File.RealAllText("nomefile.txt");

Girando sul sistema operativo Windows, la Virtual machine tradurrà questa richiesta con il sottoinsieme di funzioni presenti nel Kernel del sistema operativo per leggere il file in questione; lo stesso codice, girando su Linux, non dovrà essere modificato e personalizzato per questo sistema operativo, e ci penserà Mono a tradurre la richiesta di lettura del file con le corrette richieste al Kernel di Linux. I benefici sono facilmente comprensibili visto che non c'è alcuna perdita di tempo nel convertire nessuna riga nel nostro codice per permettere la corretta esecuzione del nostro software su più sistemi operativi. La semplicità dell'esempio qui sopra non deve però illudere: un software non si basa sempre per chiamate semplici ma spesso anche con procedure proprie della macchina su cui gira. Una windows forms come quella di cui ho postato un esempio qualche tempo fa, in ambiente Mono emula l'aspetto e il funzionamento delle finestre di Windows:

test mono 2.4 su ubuntu

Possiamo utilizzare anche librerie presenti per i sistemi operativi di nostro interesse. Qui avevo parlato per esempio delle GTK che girano perfettamente sia su Windows che su Linux - su Mac non lo so, perché di questa macchina non me ne frega nulla. Già molti software utilizzano questa strada, uno tra tanti Pidgin, il programma di messaggistica istantanea presente su molti sistemi operativi - anche se qui non si parla di Mono/java, ma ricompilazione del codice per le macchine interessate. Ed è proprio su questo punto che volevo andare a parare con questo mio post.

Il Qt toolkit, sviluppato dalla QT Software - prima Trolltech e in parte sovvenzionata da Nokia - è un framework che gira sui principali sistemi operativi: Windows, Mac e Linux (e altri SO per dispotivi mobili). Non è solo una libreria grafica, ma un framework completo che permette la gestione dei file, xml, tcp, database, grafica 2D, 3D con le OpenGL, audio e altro. E' utilizzabile con molti linguaggi, dal C++ al Python e Java. Da quel che ne so io, era nato un progetto per il loro utilizzo anche on il Framework .NET, ma da quel che ho letto sembra che tale progetto sia fermo... felice di essere smentito. Forse in ambiente Windows, Qt non è molto conosciuto, ma basti sapere che in ambiente Linux, insieme alle GTK su cui su basa il desktop manager Gnome, è molta conosciuta e utilizzata visto che su di essa si basa il secondo desktop manager più utilizzato, Kde. In ambiente Windows il software più conosciuto che utilizza questo toolkit è VLC, il programma per la visione di qualsiasi formato audio e video. Inoltre Nokia sta puntando molto su questa tecnologia per il suo sistema operativo Symbian per dispositivi mobili, dunque si presenta un probabile futuro roseo visto la posta in gioco di un mondo del portabile in continuo fermento per le numerose notivà (l'argomento meriterebbe una trattazione a sé, ma la voglia non c'è e dunque non ci provo nemmeno).

Oltre al toolkit è disponibile un ambiente di sviluppo integrato dal nome Qt Creator. Oltre all'editor di risorse come interfacce grafiche, possiede al suo interno un ambiente di sviluppo basato sul C++. Scaricabile gratuitamente la versione LGPL si ha a disposizione un editor completo per le interfacce grafiche e per la scrittura del codice C++ con tanto di intellisense, come detto, un debugger e se scaricata la versione SDK, anche la documentazione completa. Va innanzitutto detto che per la versione per Linux, si deve installare manualmente il compilatore g++. Nulla di difficile: nel caso di Ubuntu è sufficiente installare il macro pacchetto build-essential per avere già a disposizione tutto il necessario. Su Windows viene installato di default la versione per questo sistema operativo di mingw, che non è altro che la versione per questo sistema operativo del compilato c++, linker e altri strumenti. Dopo l'installazione saranno presenti anche numerosi esempi ben documentati per le principali funzioni messe a disposizione dal toolkit Qt. Nelle demo è impressionante trovare anche un browser con tanto di flash funzionante basato sul webkit - maggiormente compatibile con gli standard di IE; dunque se avete la necessità di personalizzare il browser secondo le proprio necessità ora si può partire da una base già bella pronta:

Pagina web sul browser in Qt

Gli esempi preposti si possono dividere in due macro categorie: tutorial con codice completo e vere e proprio demo. Nei primo si possono trovare esempi anche semplici, utili per impratichirsi con questo toolkit, nelle demo troviamo esempi con codice sorgente molto più avanzi, come il browser qui sopra o altri, come il tool grafico seguente che mostra alcune potenzialità grafiche:

Esempio grafico con Qt

Ma i vantaggi, come ho cercato di dire precedentemente, non si basano solo sulla potenzialità di questo framework, da dalla compatibilità che possiamo avere, senza il minimo sforzo - o ridotto al minimo, per vedere il nostro codice ricompilato su altre macchine e vedere il tutto funzionare. Tra gli esempi troviamo quello che mostra l'utilizzo delle Multiple document interface (MDI). Su Linux in Gnome:

mdi su Linux e Gnome e Qt

Stesso codice ricompilato su Windows:

MDI su windows e Qt

Dialog con tab su Linux:

Dialog con tab su linux e Qt

Su Windows:

Dialog con tab su windows e Qt

Un semplice Address book su Windows:

Adress book su Windows e Qt

Su Linux:

Adress book su linux e Qt

Tra gli esempi si trova codice utile per qualsiasi scopo: dal 2D, alle utility per uno screenshot:

Screenshoot scritta in c++ e Qt

Anche esempi per il Drag & drop, per la gestione dei file, della System tray, per la visualizzazione di chart; su Windows:

Chart su Windows con Qt

Su Linux:

Chart su Linux con Qt

Ma non solo, anche esempi sull'utilizzo di database, tcp, socket, e molto altro. Si è visto prima l'esempio di un browser completo, anche un client Torrent è disponibile con tanto di codice e perfettamente funzionante:

Selezione del torrent con il client Torrent scritto con Qt

Download con il client Torrent scritto con Qt

E sempre da questo framework, possiamo gestire/ascoltare anche gli MP3:

MP3 player scritto in C++ e Qt

Per esigenze mie, che non sto a spiegare perché sono fatti miei, ho iniziato a utilizzare le Qt e dopo i primi problemi con la sintassi del C++ non più utilizzata da anni, mi sono trovato presto a mio agio: spesso mi sono trovato dinanzi a oggetti che ricordano da vicino il Framework .NET o Java. Per esempio, per l'utilizzo di stringhe, già facilitata in C++ grazie alle STL che ci permette di scrivere:

#include <string>
using namespace std;
...
string name="AZ";

Con le Qt abbiamo a disposizione la classe QString:

#include <QString>
...
QString name="AZ";

Nella quale troviamo tutte le funzioni di cui un programmatore normalmente ha bisogno: replace, substring, find, startWith, endWith e così via. E la vicinanza che io ho trovato con gli oggetti del Framework .NET, la si può vedere nella gestione delle liste. Quello che scriviamo in C#:

List<string> coll=new List<string>();
coll.Add("AZ");
coll.Add("...");
string name=coll[0];

Con le Qt in C++:

QList<QString> coll;
coll.append("AZ");
coll.append("...");
// Oppure:
// coll << "AZ" << "...";
QString name=coll.at(0);

Per le varie conversioni tra oggetti, sono presenti i vari metodi:

QString str="12";
int num=str.toInt();

Oppure il più generico oggetto QVariant che ci permette il travaso tra i vari oggetti del Framework Qt. Altro oggetto molto utilizzato per la gestione delle date è il QDateTime:

QDateTime dt = QDateTime::currentDateTime();
QDateTime xmas(QDate(dt.date().year(),12,24), QTime(17,00));
int secToXmas = dt.secsTo(xmas);

Se si vuole scrivere un file:

#include <QTextStream>
#include <QFile>
int main()
{
QFile data("myfile");
if (data.open(QFile::WriteOnly)) {
QTextStream out(&data);
out << "Contenuto file di testo" << endl;
}
}

Per leggere:

QFile dataread("myfile");
if (dataread.open(QFile::ReadOnly)) {
QTextStream in(&dataread);
QString content=in.readAll();
dataread.close();
}

Per la gestione delle directory c'è QDir:

QString home = QDir::homePath();

Per avere la lista presenti:

#include <iostream>
#include <QTextStream>
#include <QDir>
int main(int argc, char *argv[])
{
QDir dir;
QStringList filters;
filters << "*.exe" << "*.cpp";
dir.setNameFilters(filters);
QFileInfoList list = dir.entryInfoList();
for (int i = 0; i < list.size(); ++i) {
QFileInfo fileInfo = list.at(i);
std::cout << QString("%1").arg(fileInfo.fileName()).toStdString();
std::cout << endl;
}
return 0;
}

Ho trovato anche ben fatto la gestione del multi language: grazie a dei file Xml si possono definire le label che da codice possiamo caricare e visualizzare grazie al metodo tr():

<!DOCTYPE TS><TS>
<context>
<name>FirstPanel</name>
<message>
<source>Example</source>
<translation>Esempio</translation>
</message>
...
</context>
<context>
<name>SecondPanel</name>
<message>
<source>Code</source>
<translation>Codice</translation>
</message>
...
</context>
</TS>

Il file xml può contenere anche più sezioni di codice come si vede sopra. Per poter richiamare il testo:

QApplication app(argc, argv);
QTranslator translator=translator.load(QString("nomefile"));
app.installTranslator(&translator);
QString source=tr("Example");

Nella gestione delle interfacce grafiche mi sono immediatamente scontrato con un utilizzo alternativo degli eventi. Le Qt introducono un nuovo modo per la comunicazione di oggetti: i signals e gli slots. Avendo un pulsante nella windows application, se vogliamo che al click di un button sia eseguito il nostro codice, doabbiamo collegare il signal del click del button ad uno slot presente nel codice (anche se è possibile farlo da interfaccia grafica). Per esempio, avedo un QButton e una QLabel (tutti gli oggetti all'interno di questo Framework iniziano con la lettera Q) nell'interfaccia grafica:

connect(ui->ButtonAZ, SIGNAL(clicked()), this, SLOT(ChangeTextAZ()));

connect crea il collegamento al click sul button al metodo ChangeTextAZ presente all'interno della stessa classe (this) dell'interfaccia grafica. Al click sul button sarà richiamata la funzione apposita - per esempio:

void MainWindow::ChangeTextAZ()
{
QString cc=QDateTime::currentDateTime().toString();
ui->label->setText(cc);
}

Per scollegare uno slot dal signal:

ui->ButtonAZ->disconnect(SIGNAL(clicked()));

Sia ben chiaro da subito che il loro utilizzo non si limita agli eventi dei button nella pagina, ma anche ai singoli oggetti creati da noi. Per esempio, la classe scritta in C++ nel seguente modo:

class Person
{
public:
Person() { Age=0;}
int GetAge() { return Age; }
void setAge(int age) { Age=age;}
private:
int Age;
};

Scritta utilizzando gli oggetti di Qt con il supporto dei signals e slots, diverrebbe:

#include <QObject>
class Person:public QObject
{
QObject // macro per l'inclusione degli oggetti per l'utilizzo delle funzionalità aggiuntive di Qt
public:
Person() { Age=0;}
int GetAge() { return Age; }
signals:
void changeAge(int age);
public slots:
void setAge(int age)
{
if (Age!=age)
{
Age=age;
emit changeAge(age);
}
}
private:
int Age;
};

Ho aggiunto il signal changeAge e modificato la funzione setAge impostandolo come slot. Questo mi permette di collegare questo oggetto ad eventi che possono essere lanciati da un altro oggetto collegato. Se usiamo il codice seguente:

Person a,b;
connect(&a, SIGNAL(changeAge(int)), &b, SLOT(setAge(int)));
a.setAge(36);
int c=b.GetAge(); // i conterrà 36

Creati due oggetti, a e b, e collegati, assegnando il valore intero 36, la funzione setAge controllerà inizialmente che non sia già stato assegnato questo valore (per evitare loop), altrimenti modificherà la variabile intera Age e scatenerà l'evento ChangeAge grazie a emit che, collegato al setAge dell'oggetto B, ne modificherà il valore.

Come detto in precedenza, possiamo utilizzare qualsiasi editor per l'utilizzo del framework Qt, anche Visual Studio con questo add-in. Se vogliamo un editor che sia cross-platform possiamo utilizzare anche Eclipse, oppure l'editor nativo delle Qt: QtCreator. Disponibile per Windows, Mac e Linux, è un ottimo e leggero editor che comprende debug, help e intellisense nella stesura del codice, e comprende un buon editor per la creazione delle interfacce grafiche. Su una macchina con Linux (Ubuntu 9.10) ho potuto utilizzarlo senza particolari problemi con una macchina con soli 512MB; con Windows è utilizzabile con quantitativi di ram minimi; su Mac non l'ho provato perché non me ne importa niente di tali macchine. Se dovessi confrontarlo con altri editor come Visual Studio (uno dei pochi ambienti di sviluppo che conosco bene), il QtCreator paga pegno per l'intellisense non al livello di Visual Studio: nella visualizzione dei metodi non si ha alcun aiuto del tipo il numero di parametri, overload ed eventuali tipi restituiti:

Intellisense in QtCreator

L'help è di buon livello, ma spesso si trovano poche righe di descrizione e nessun esempio sull'utilizzo. Il debug fa il suo lavoro:

Debugger nel QtCreator

E anche la gestione dei thread in debug è buono anche se inferiore all'attuale presende in Visual Studio 2010. L'editor delle interfacce grafiche è ben fatto e, capite le basi di Qt, permette la creazione di qualsiasi interfaccia:

Esempio di interfaccia grafica in QtCreator

In cantiere è già presente il nuovo editor, la versione 2.0, che introdurrà molte novità, tra le quali il QML (Qt Meta-Object Language) che permette la creazione di interfacce grafiche in un meta linguaggio interno molto seplice e le Qt Declarative Module e altre novità; per una lista completa si veda questo link.

Ok, dopo questa breve divagazione, la domanda lecita potrebbe essere: "Ma quanto pesa tutto ciò negli eseguibili?". Su Linux praticamente nulla visto che le Qt sono installabili dai repository e nel caso di Kde sono già installate di default. Su Windows la risposta è il solito e stancante dipende! Dipende da quanti e quali oggetti del Framework Qt vengono utilizzati. Per una mia windows application ho dovuto includere nella directory dell'eseguibile i seguenti file:

  • QtCore4.dll (2.359 Kb)
  • QtGui4.dll (9.293 Kb)
  • QtXml4.dll (389 Kb)
  • libgcc_s_dw2-1.dll (42 Kb)
  • mingwm10.dll (12 Kb)
  • qjpeg4.dll (188 kb)

Qui parlo di un piccolo problema che avevo riscontrato all'esecuzione di tale codice su Windows. Inizialmente installato tale software su un'altra macchina con Windows Vista non mi venivano visualizzate le immagini. Solo dopo scopro che è necessario utilizzare la dll qjpeg4. Secondo la documentazione la inscerisco nella directory dove c'è l'eseguibile, più precisamente, in plugins\imageformats, e mi accorgo che le immagini non vengono ancora visualizzate. Solo dopo una ricerca in internet, scopro che è necessario aggiungere il file di configurazione nella stessa directory dell'eseguibile, con il nome qt.conf e con questo contenuto:

[Paths]
plugins=./plugins

Questo problema sotto Linux non c'è. Comunque, aggiungendo che l'esegubile era per il mio esempio sotto al mega, il tutto si è risolto in circa 12 MB - l'applicativo d'esempio era una windows forms con effetti 2D e gestione di foto e dati informativi personali. Per applicazioni che devono diversificare il tipo di compilazione e inclusioni oggetti specifici del sistema in cui gira, è sufficiente mettere mano al file nomeprogetto.pro:

TARGET = Esempio
TEMPLATE = app
SOURCES += main.cpp \
objects.cpp
HEADERS += objects.h
FORMS += dialog.ui
RESOURCES += Resources.qrc
INCLUDEPATH += ./include
unix:LIBS += -L/usr/X11R6/lib \
-LMySharedClass
win32:LIBS += ./MySharedClass.a
DESTDIR = ./final

Precedendo con win32: o unix: possiamo specificare, nell'esempio sopra, quale library includere utilizzare nel caso di Windows (nel primo caso) o di Linux (nel secondo) - è presente anche macx: per la cronaca... Con questo trucchetto possiamo anche includere anche i nostri file .cpp da compilare dipendentemente dal sistema operativo su cui sarà compilata l'applicazione:

win32 {
SOURCES += hellowin.cpp
}
unix {
SOURCES += hellounix.cpp
}

Magari in futuro pubblicherò un esempio completo di un'applicazione scritta in Qt compilabile sia su Windows che Linux senza alcuna modifica che sfrutti librerie esterne.

Un'altra domanda lecita potrebbe essere: "Quanto è performante il codice compilato con questo ambiente di sviluppo se confrontato con quello prodotto dai compilatori in Visual Studio?". Sinceramente non ho mai trovato documentazione a riguardo e i test banali fatti personalmente non mi hanno dato alcuna risposta valida a questo quesito.

Un altro pregio che ho trovato nel mondo Qt, è la ricca documentazione che si può trovare sia sul sito ufficiale che in molte altre community. Per esempio, cito la internazionale Qt Centre. In Italia una giovane community si è affacciata da poco tempo e propone già dei buoni contenuti per la lingua Italiana.

Basta, ho scritto troppo. Si può però capire come questo framework mi sia piaciuto. Non ho potuto scoprire tutto l'immenso mondo nascosto dietro alle due lettere Qt causa il poco tempo libero che ho potuto dedicare alla semplice scoperta di questa tecnologia, ma darei un voto molto alto - naturalmente è un parere completamente PERSONALE, dunque di eventuali critiche non me ne frega niente.

Ma dunque è tutto oro quel che luccica? No. Ho riscontrato vari problemini, alcuni dei quali citati prima. Innanzitutto, nella versione per Windows ho notato strane anomalie dell'ambiete di sviluppo QT Creator. Per esempio, su un portatile con Windows XP ho riscontrato errori nella ricompilazioni dei sorgenti presenti negli esempi, oppure l'help non funzionante - con Linux/Ubuntu invece nessuno di questi problemi. Inoltre con codice C++ scritto non utilizzando gli oggetti di Qt, ho notato blocchi casuali del debugger su entrambi i sistemi operativi (ma questo potrebbe essere dovuto a qualche sciocchezza scritta da me: la mia poca esperienza in C++ potrebbe esserne la causa principale).

Inoltre ho notato che il compilatore va in confusione nel caso che ho descritto nell'esempio qui sopra riguardante l'oggetto che si interfaccia con i signals e slots. Sempre casualmente, se si scrive un proprio oggetto e si aggiunge in un secondo tempo il supporto e l'inheritance a QObject, il compilatore non riesce a riconoscere questo nuovo oggetto ed emette l'errore: "Undefined reference to vtable". Da quel che ho visto il problema è dovuto dal fatto che QtCreator aggiunge un file con il moc_nomeclasse.cpp che viene creato solo se all'aggiunta nell'ambiente di sviluppo di tale classe viene subito definito l'inheritance con QObject; l'unica soluzione è cancellare tale classe, con i relativi file, e aggiungerla nuovamente al progetto.

Ora attendo la nuova versione sia di QtCreator che del Framework stesso dove importanti novità saranno introdotte. Basta mi fermo qui, perché altrimenti mi viene voglia di spalare ***** su altre tecnologie... So che ho solo sfiorato l'argomento Qt, e che sicuramente ho tralasciato molti altri aspetti importanti. Ma - è un mio punto di vista - la trasportabilità del codice e poterlo riutilizzare su più piattaforme è - e sarà - sempre più importante, senza dover riscrivere ogni volta parte del codice o reimplementare funzioni dello stesso. Il mondo non è solo Windows, e due...

Naturalmente tutto quanto esposto qui, è sotto licenza IMHO! Il mio tempo libero lo utilizzo come mi pare. Oggi in Spagna ha vinto Lorenzo in motogp e tra sette giorni inizia il giro d'Italia finalmente; oggi piove ed ho i tergicristalli della macchina rovinati da parecchio tempo e non ho avuto ancora il tempo di cambiarli.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese