Qt Lezione4 Parte2: creare un custom widget plugin per Qt Designer
1. Creare un custom widget plugin
per Qt Designer
parte 2
Premessa
Questa presentazione è rilasciata sotto Licenza
Creative Commons: Attribution-NonCommercial-NoDerivativeWorks
(http://creativecommons.org/licenses/by-nc-nd/3.0/deed.it).
Questo documento può quindi essere riprodotto senza violare nessuna legge, sia in versione elettronica, sia in versione
cartacea, purché sia riprodotto integralmente in tutte le sue parti, compresa la pagina che contiene queste informazioni:
Versione originale scaricabile dal sito
http://www.sereno-online.com/site/
Tutti i marchi riportati in questa pubblicazione appartengono ai rispettivi proprietari.
Link Utili
Qui di seguito riporto alcuni link utili per chi usa quotidianamente l’ambiente di sviluppo Qt e vuole confrontarsi con
altri sviluppatore, utenti e semplici appassionati di questo toolkit gratuito ed open source.
Gruppo Programmatori Italiani Qt Software (GPIQt)
http://www.facebook.com/inbox/?ref=mb#/group.php?gid=81561439535
qt in Italy
http://qt-apps.org/groups/?id=17
qtitaliantranslators
http://gitorious.org/+qtitaliantranslators
Autore P. Sereno http://www.sereno-online.com/site
2. Scopo
Nella prima parte di questa lezione abbiamo trattato la derivazione della classe QWidget e la creazione di un custom
widget. Per poter usare il nostro custom widget come tutti gli altri controlli grafici di Qt, dobbiamo trasformarlo in un
plugin per Qt Designer.
Cos’è un plugin di Qt designer?
Qt Designer, l’ambiente di prototipazione rapida di Qt, è uno strumento molto potente e flessibile che può essere esteso
in molti modi. Un modo molto pratico per estendere le funzionalità di Qt Designer è quello di realizzare librerie
dinamiche (i plugin appunto) che Qt Designer va a caricare allo startup e che metterà a disposizione come controlli
custom allo stesso modo di tutti gli altri widget del Qt toolkit.
Passo 1: come si crea un plugin per Qt Designer
Non c’è modo migliore per spiegare come si realizza un plugin che illustrarne il codice sorgente.
Nella prima parte di questa lezione abbiamo realizzato una nuova classe di nome QLed, ora ci occuperemo di scrivere un
plugin che contiene QLed al suo interno e si interfaccia con il designer di Qt. Per fare ciò scriviamo due files sorgente
qledplugin.h e qledplugin.cpp.
Iniziamo da qledplugin.h:
#ifndef CUSTOMWIDGETPLUGIN_H
#define CUSTOMWIDGETPLUGIN_H
#include <QDesignerCustomWidgetInterface>
class QLedPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
QLedPlugin(QObject *parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget *createWidget(QWidget *parent);
void initialize(QDesignerFormEditorInterface *core);
private:
bool initialized;
};
#endif
Per prima cosa dobbiamo includere <QDesignerCustomWidgetInterface> per poter usare l’omonima classe e quindi
possiamo ora definire la nostra classe derivando come segue:
class QLedPlugin : public QObject, public QDesignerCustomWidgetInterface
questo perchè la nostra classe che è un Qobject è anche una classe di interfaccia con il Qt Designer.
Autore P. Sereno http://www.sereno-online.com/site
3. Le istruzioni che seguono
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
Permettono al meta object compiler di preparare tutto il codice “multipiattaforma” e di riconoscere la nostra classe come
interfaccia. In altre parole, nella costruzione di un widget plugin ricordiamoci sempre di queste due macro quando
scriviamo la classe.
Passiamo ora ai metodi pubblici
public:
QLedPlugin(QObject *parent = 0); // è il costruttore
bool isContainer() const; // il widget è un oggetto
container?
bool isInitialized() const; // il widget è inizializzato?
QIcon icon() const; // restituisce
l’icona del widget
QString domXml() const; // la stringa domXML
QString group() const; // il gruppo del widget
QString includeFile() const; // l’header file del widget
QString name() const; // il nome del widget
QString toolTip() const; // il tooltip del widget
QString whatsThis() const; // la stringa
whatsthis
QWidget *createWidget(QWidget *parent); // il metodo di creazione
void initialize(QDesignerFormEditorInterface *core); // il metodo di inzializzazione
ed infine le proprietà
private:
bool initialized;
Vediamo nel dettaglio ora l’implementazione dei metodi visti sopra.
Autore P. Sereno http://www.sereno-online.com/site
5. " <bool>false</bool>n"
" </property>n"
" <property name="whatsThis" >n"
" <string>Led widget</string>n"
" </property>n"
" <property name="color" >n"
" <enum>QLed::Red</enum>n"
" </property>n"
"</widget>n";
}
QString QLedPlugin::includeFile() const
{
return "qled.h";
}
Q_EXPORT_PLUGIN2(customwidgetplugin, QLedPlugin)
Per prima cosa dobbiamo ricordarci degli header file
#include "qled.h"
#include "qledplugin.h"
#include <QtPlugin>
Fatto ciò possiamo concentrarci sul costruttore
QLedPlugin::QLedPlugin(QObject *parent)
: QObject(parent)
{
initialized = false;
}
Questo metodo è banale e deve essere fatto esattamente così, per qualsiasi widget plugin; solo così infatti il designer
funziona correttamente.
void QLedPlugin::initialize(QDesignerFormEditorInterface * /* core */)
{
if (initialized)
return;
initialized = true;
}
Anche il metodo initialize deve essere considerato come un assioma; il funzionamento interno del Qt designer ci impone
di scrivere il metodo initialize in questo modo.
QWidget *QLedPlugin::createWidget(QWidget *parent)
{
return new QLed(parent);
}
createWidget è il vero metodo responsabile della creazione del nostro custom widget; esso infatti alloca mediante la new
una nuova istanza di QLed (poiché il nostro widget deve istanziare una sola volta QLed, ecco che il meccanismo di
initialize visto prima torna utile per questo scopo).
QString QLedPlugin::name() const
{
return "QLed";
}
Questo metodo deve restituire il nome della nostra classe.
Autore P. Sereno http://www.sereno-online.com/site
6. Vediamo ora in un’unica spiegazione i seguenti metodi:
QString QLedPlugin::group() const
{
return "Lab Widgets";
}
QIcon QLedPlugin::icon() const
{
return QIcon();
}
QString QLedPlugin::toolTip() const
{
return "";
}
QString QLedPlugin::whatsThis() const
{
return "";
}
Tutti i widget disponibili vengono raggruppati in diversi contenitori nella toolbar laterale a sinistra della finestra di Qt
designer. In questo caso si è scelto di creare un nuovo contenitore per QLed etichettato “Lab Widgets”
Icon() restituisce l’icona associata al nostro widget; nel caso del nostro esempio l’icona è vuota, ma qui potremo inserire
una qualsiasi immagine che rappresenta il nostro widget.
toolTip() restituisce il Tool Tip del nostro widget (vuoto nel nostro caso)
whatsthis() restituisce la stringa di aiuto (what’s this) che è vuota nel nostro caso.
Arriviamo ora alla novità delle Qt 4.X rispetto la precedente versione (Qt 3.X) e cioè il metodo seguente:
QString QLedPlugin::domXml() const
{
return "<widget class="QLed" name="qLed">n"
" <property name="geometry">n"
" <rect>n"
" <x>0</x>n"
" <y>0</y>n"
" <width>100</width>n"
" <height>100</height>n"
" </rect>n"
" </property>n"
" <property name="toolTip" >n"
" <string>Binary Led</string>n"
" </property>n"
" <property name="value" >n"
" <bool>false</bool>n"
" </property>n"
" <property name="whatsThis" >n"
" <string>Led widget</string>n"
" </property>n"
" <property name="color" >n"
" <enum>QLed::Red</enum>n"
" </property>n"
"</widget>n";
}
domXML ci consente di specificare in modo testuale, tramite XML appunto una serie di proprietà di default del nostro
widget. Il fatto di poter usare questa definizione testuale permette di modificare un custom widget in modo rapido ed
Autore P. Sereno http://www.sereno-online.com/site
7. efficiente. Nell’esempio sopra riportato possiamo vedere che si è impostata la geometria di default del widget, così come
il valore, il colore etc.
terminiamo infine con il metodo
QString QLedPlugin::includeFile() const
{
return "qled.h";
}
che ci consente, nel momento in cui usiamo il compilatore di interfaccia utente (UIC), di specificare dove si trova il file
header del nostro custom widget plugin. E’ importante sottolineare che se l’header file non si trova nella directory
“canonica” di include, è necessario riportare in questa stringa un path che consenta poi al compilatore di ritrovare il file .h
concludiamo infine con la macro
Q_EXPORT_PLUGIN2(customwidgetplugin, QLedPlugin)
Che ci consente di esportare il nostro plugin durante il processo di compilazione e linking e generare correttamente la
libreria dinamica per Qt Designer.
Installazione del plugin
A questo punto il nostro plugin è pronto. Dopo aver compilato il tutto ricordiamoci di posizionare il file di libreria
dinamica (il plugin appunto) nella directory plugin del Qt Designer ed inoltre ricordiamo anche che il file qled.h deve
essere posizionato in una directory di include nota al processo di compilazione.
Ovviamente queste operazioni di “copia” della libreria dinamica e del file .h possono essere automatizzate con qmake per
generare così il classico “make install” (che si occuperà perciò di fare l’installazione del plugin). Si lascia al lettore, come
esercizio finale, la realizzazione di questo “script” per qmake.
Considerazioni finali
Questa lezione è parte di un ciclo reso disponibile gratuitamente in Internet sul sito
http://www.sereno-online.com/site
Come preannunciato, le cose si sono complicate a partire da questa lezione. Per capire bene come si disegna un custom
widget è consigliabile partire dal codice sorgente di esempio e provare a modificarne alcune parti per vedere l’effetto. Un
utile ausilio per la comprensione dell’esempio è il Qt Assistano che fornisce molte informazioni dettagliate circa le classi
i metodi e riporta utili esempi ove possibile.
A questo punto ricordo che ogni commento o richiesta di informazioni rappresenta un utile punto di partenza per nuove
lezioni o miglioramenti e auguro
Buon divertimento!
Paolo
Autore P. Sereno http://www.sereno-online.com/site