Qt Lezione4 Parte1: creare un custom widget plugin

3,235 views

Published on

Come si scrive un custom widget plugin da inserire in Qt Designer? Questo tutorial ci spiega come.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
3,235
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
202
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Qt Lezione4 Parte1: creare un custom widget plugin

  1. 1. Mini Guide Qt Creare un custom widget plugin per Qt Designer parte 1 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. 2. Mini Guide Qt Scopo Dopo aver trattato nelle precedenti lezioni la realizzazione di applicazioni Qt mediante le classi QMainwindow, QDialog, vediamo in questa lezione cos’è e come si scrive un custom widget plugin. Cos’è un custom widget plugin? Un custom widget plugin è un “custom widget”, cioè un widget grafico particolare, costruito ad hoc in base alle esigenze di un’applicazione. Nell’esempio illustrato in figura seguente si vede un custom widget che simula nella grafica un LED, cioè uno di quegli indicatori luminosi che tutti conosciamo e che si trovano sulle nostre radio, televisori, amplificatori etc… Il LED della nostra figura è una classe di nome QLed che fa parte di una libreria dinamica (caricata a run time) dal Qt Designer. Questa libreria è stata costruita ricorrendo agli strumenti messi a disposizione dal Qt toolkit ed è un modo semplice e flessibile di estendere l’ambiente di sviluppo (Qt Designer appunto) con nuovi componenti grafici che possono essere posizionati ed impostati in modo “visual”. L’argomento custom widget plugin è complesso ed articolato, in questa lezione non tratteremo tutti gli aspetti della sua realizzazione, bensì ci focalizzeremo sulla derivazione dalla classe QWidget (classe da cui derivano tutti i componenti grafici di Qt) e sull’implementazione dei metodi principali di QLed. In altre parole faremo un custom widget. La trasformazione del custom widget in plugin sarà oggetto della seconda parte della lezione. Per questa lezione analizzeremo quindi solo i files qled.h e qled.cpp. I files sorgenti sono scaricabili come sempre alla pagina di download del Blog: http://www.sereno-online.com/site e sono quelli della lezione 4. Autore P. Sereno http://www.sereno-online.com/site
  3. 3. Mini Guide Qt Passo 1 Vediamo il file qled.h #ifndef QLED_H #define QLED_H #include <Qt> #include <QWidget> #include <QtDesigner/QDesignerExportWidget> class QDESIGNER_WIDGET_EXPORT QLed : public QWidget { Q_OBJECT Q_ENUMS( LedColor ) Q_PROPERTY(bool value READ value WRITE setValue); Q_PROPERTY(LedColor color READ color WRITE setColor); public: enum LedColor {Red=7,Green=8,Blue=9,Yellow=12}; QLed(QWidget *parent = 0); bool value() const { return m_value; } LedColor color() const { return m_color; } public slots: void setValue(bool); void setColor(LedColor); void toggleValue(); protected: bool m_value; LedColor m_color; void paintEvent(QPaintEvent *event); }; #endif Tralascio la spiegazione del perché il file header in questione è protetto dalla ifndef “a panino”, qualsiasi manuale C spiega in dettaglio il motivo. Subito dopo troviamo le include #include <Qt> #include <QWidget> #include <QtDesigner/QDesignerExportWidget> queste ci servono perchè stiamo progettando di derivare una classe (e quindi ci servono Qt e QWidget) e poi farne un plugin per Qt Designer (e quindi ci serve QtDesigner/QdesignerExportWidget). Ed ora dobbiamo preoccuparci di definire la nostra classe: class QDESIGNER_WIDGET_EXPORT QLed : public QWidget la nostra classe (di nome QLed) sarà derivata da Qwidget e dovrà essere un plugin (e qui serve la macro QDESIGNER_WIDGET_EXPORT, ma di questo ne parleremo meglio nella seconda parte). Arriviamo ora al dunque: Q_OBJECT Q_ENUMS( LedColor ) Q_PROPERTY(bool value READ value WRITE setValue); Q_PROPERTY(LedColor color READ color WRITE setColor); Autore P. Sereno http://www.sereno-online.com/site
  4. 4. Mini Guide Qt Q_OBJECT Dobbiamo SEMPRE ricordarci di inserire questa macro se all’interno della classe vogliamo usare il toolkit Qt. Questa macro informa il meta object compiler (il MOC) che occorre fare una serie di azioni per aggiungere il codice necessario all’esecuzione sulla piattaforma del nostro widget. Questa macro è inoltre utile per informare il MOC che potrebbe esserci qualche stringa da preparare per la traduzione ( usare sempre “tr()” ). Per non perderci in troppi dettagli, ricordiamo sempre di scrivere questa macro all’inizio della classe- Q_ENUMS(LedColor) Con quest’altra macro informiamo il MOC che stiamo definendo un enumerativo Q_PROPERTY(bool value READ value WRITE setValue); Q_PROPERTY(LedColor color READ color WRITE setColor); Con queste macro definiamo le proprietà del nostro LED: il valore, booleano (il LED è acceso o spento?) il colore vediamo la prima proprietà bool value READ value WRITE setValue E’ un booleano, definiamo che il metodo di lettura (READ) si chiama value, il metodo di scrittura (WRITE) si chiama setValue. Questa notazione è la stessa usata dai Trolls sin dalla notte dei tempi. Il consiglio quindi è quello di mantenerla per rimanere uniformi e, se un giorno metteremo il nostro codice in rete, faciliteremo la lettura a chi lo scaricherà. Vediamo ora i metodi pubblici public: enum LedColor {Red=7,Green=8,Blue=9,Yellow=12}; QLed(QWidget *parent = 0); bool value() const { return m_value; } LedColor color() const { return m_color; } La keyword public sta appunto ad indicare che questi sono metodi pubblici... 1) Per prima cosa l’enumerativo enum LedColor {Red=7,Green=8,Blue=9,Yellow=12}; il colore del nostro led è un enumerativo di nome LedColor e può assumere i valori indicati tra parentesi. 2) Il costruttore QLed(QWidget *parent = 0); il parametro QWidget *parent =0 rappresenta il puntatore al padre (il default = 0 indica un oggetto TOP LEVEL, quindi senza padre) Autore P. Sereno http://www.sereno-online.com/site
  5. 5. Mini Guide Qt 3) il metodo che restituisce il valore: value bool value() const { return m_value; } è un booleano. 4) il metodo che restituisce il valore: color LedColor color() const { return m_color; } Che ovviamente restituisce un valore di tipo LedColor Passiamo ora agli slot public slots: void setValue(bool); void setColor(LedColor); void toggleValue(); Perché li dobbiamo definire slot? Non basterebbe dire che sono metodi pubblici? La risposta è.. certo! Ma così facendo non potremo MAI usarli con la connect. La connect è quel meraviglioso meccanismo inventato da Eirik Chambe Eng e Haavard Nord su una panchina del molo di Oslo agli albori dell’avventura Trolltech che serve per risolvere il problema di far comunicare gli oggetti di Qt senza preoccuparsi della piattaforma hardware che c’è sotto! Gli slot che vogliamo dare al nostro LED sono: setValue = lo slot che imposta il valore setColor = lo slot che imposta il colore del LED toggleValue = lo slot incaricato di cambiare lo stato del led (da spento ad acceso e viceversa) Arriviamo infine alle parti protected protected: bool m_value; LedColor m_color; void paintEvent(QPaintEvent *event); m_value = il valore del LED (false = spento; true = acceso) m=color = il colore del led quando acceso (rosso,verde,blu,giallo) paintEvent = questo metodo è FONDAMENTALE, poiché dobbiamo disegnare noi stessi l’aspetto grafico del nostro budget e lo facciamo proprio andando a scrivere questo metodo. painEvent viene richiamato dal window manager ogni volta che è necessario ridisegnare il widget (perché viene spostato, ridimensionato, portato in primo piano e non più nascosto dietro a qualcos’altro) Autore P. Sereno http://www.sereno-online.com/site
  6. 6. Mini Guide Qt Per quanto riguarda qled.h abbiamo finito. Ora arriva il bello! Passo 2 Vediamo il file qled.cpp Iniziamo con il costruttore QLed::QLed(QWidget *parent) : QWidget(parent) { m_value=false; m_color=Red; setMinimumSize(QSize(50,50)); } Il costruttore non fa altro che inizializzare il valore del LED (false), il colore (rosso) e informare il layout manager che la sua dimensione minima è 50x50 pixel (questo serve se il custom widget viene inserito in un layout manager che cerca la dimensione e posizione ottimale per i diversi componenti dentro ad un contenitore (finestra o altro widget). E adesso vediamo paintEvent void QLed::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.setWindow( -50,-50,100,100); painter.setPen(Qt::white); painter.drawArc(-25,-25,50,50,0,5670); painter.drawArc(-34,-33,66,66,0,5670); painter.setPen(Qt::darkGray); painter.drawArc(-34,-33,66,66,3400,3000); if(m_value) { QRadialGradient radialGrad(QPointF(-8, -8), 20); radialGrad.setColorAt(0, Qt::white); QColor color; switch(m_color) { case Red: color=QColor(Qt::red); break; case Green: color=QColor(Qt::green); break; case Blue: color=QColor(Qt::blue); break; case Yellow: color=QColor(Qt::yellow); break; default: color=QColor(Qt::red); break; } radialGrad.setColorAt(1, color); QBrush brush(radialGrad); painter.setBrush(brush); painter.setPen(Qt::black); painter.drawEllipse(-25,-25,50,50); Autore P. Sereno http://www.sereno-online.com/site
  7. 7. Mini Guide Qt } else { QRadialGradient radialGrad(QPointF(-8, -8), 20); radialGrad.setColorAt(0, Qt::white); radialGrad.setColorAt(1, Qt::lightGray); QBrush brush(radialGrad); painter.setBrush(brush); //painter.setPen(Qt::black); painter.drawEllipse(-25,-25,50,50); } } E qui le cose si complicano. Procediamo con ordine. QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.setWindow( -50,-50,100,100); painter.setPen(Qt::white); painter.drawArc(-25,-25,50,50,0,5670); painter.drawArc(-34,-33,66,66,0,5670); painter.setPen(Qt::darkGray); painter.drawArc(-34,-33,66,66,3400,3000); La prima istruzione la troveremo sempre in un metodo paintEvent, perché stabilisce il contesto di disegno associato al widget (sembra complicato, ma basta ricordarsi di questa istruzione se non si vuole approfondire la cosa…) La seconda istruzione serve per indicare al motore grafico di Qt di usare l’antialiasing. Con l’antialiasing i cerchi saranno più armoniosi e il testo più pulito. In altre parole… usiamolo sempre! La terza istruzione imposta le coordinate della finestra di disegno che andranno quindi da -50,-50 a 50,50. In questo modo tutta l’area di disegno viene stabilità essere quadrata e suddivisa in 100x100 pixel (fare prove con valori diversi e vedete se e cosa cambia…) La setPen seguente imposta il colore per il disegno (bianco) e successivamente si disegnano i semicerchi del LED di colore bianco e poi quello di colore grigio. Questo gioco bianco/grigio non è altro che un trucchetto per simulare un effetto 3d molto minimalista del nostro widget. Per capire meglio si possono fare un po’ di prove cambiando i colori e i valori di disegno dell’arco (punto di partenza o di arrivo, angolo di disegno). Per un approfondimento dei parametri della drawArc vi rimando al manuale di Qt. Seguono ora le linee di codice legate al valore del LED if(m_value) { QRadialGradient radialGrad(QPointF(-8, -8), 20); radialGrad.setColorAt(0, Qt::white); QColor color; switch(m_color) { case Red: color=QColor(Qt::red); break; .... nel caso di valore true (led acceso), si usa il colore selezionato (tramite lo swtch) e poi si disegna come segue: radialGrad.setColorAt(1, color); QBrush brush(radialGrad); painter.setBrush(brush); Autore P. Sereno http://www.sereno-online.com/site
  8. 8. Mini Guide Qt painter.setPen(Qt::black); painter.drawEllipse(-25,-25,50,50); Queste linee di codice usano un gradiente di colore di tipo “radiale” per abbellire l’aspetto estetico del LED e poi si disegna finalmente il cerchio (drawEllipse) che corrisponde al LEd vero e proprio. Nel caso di LED spento e cioè else { QRadialGradient radialGrad(QPointF(-8, -8), 20); radialGrad.setColorAt(0, Qt::white); radialGrad.setColorAt(1, Qt::lightGray); QBrush brush(radialGrad); painter.setBrush(brush); //painter.setPen(Qt::black); painter.drawEllipse(-25,-25,50,50); } Il giochetto è lo stesso, ma con altri colori. Autore P. Sereno http://www.sereno-online.com/site
  9. 9. Mini Guide Qt 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

×