Qt Lezione4 Parte1: creare un custom widget plugin

9

Click here to load reader

description

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

Transcript of Qt Lezione4 Parte1: creare un custom widget plugin

Page 1: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

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 sitohttp://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

Page 2: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

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.

Page 3: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

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_OBJECTQ_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_OBJECTQ_ENUMS( LedColor )Q_PROPERTY(bool value READ value WRITE setValue);Q_PROPERTY(LedColor color READ color WRITE setColor);

Page 4: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

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)

Page 5: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

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)

Page 6: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

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);

Page 7: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

}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);

Page 8: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

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.

Page 9: Qt Lezione4 Parte1: creare un custom widget plugin

Mini Guide Qt

Autore P. Sereno http://www.sereno-online.com/site

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