Questa lezione sul toolkit Qt permette di scrivere una semplice applicazione di visualizzazione immagini, i formati sono quelli più comunemente usati: JPG, BMP, PNG etc.
1. Mini Guide Qt
Creare un’applicazione di visualizzazione
immagini
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. Mini Guide Qt
Scopo
Scopo di questa terza lezione è arricchire l’applicazione creata nella seconda lezione con alcune utili
funzionalità. Il codice sorgente della terza lezione è reperibile sul sito http://www.sereno-online.com/site
alla pagina di downloads.
Questo esempio non vuole essere un’applicazione completa e con molte funzionalità, si vuole cioè evitare
di sommare troppi concetti per un’unica lezione e si vuol lasciare al lettore la curiosità di scoprire nuove
funzioni del Qt application framework.
I fondamenti di quest’applicazione sono presi da un progetto open source (QPhoton) il cui obiettivo è
quello di realizzare un programma di fotoritocco semplice da usare e poco pesante.
Buon lavoro!
Passo 1
Per prima cosa partiamo dalla main window della seconda lezione (in altre parole, possiamo recuperare il
codice sorgente della lezione numero 2), rappresentata nella figura qui sotto
Autore P. Sereno http://www.sereno-online.com/site
3. Mini Guide Qt
Passo 2
Aggiungiamo ora (in Qt Creator) una MDIArea alla nostra main window (MdiArea si trova nella toolbar a
sinistra, subito dopo la lista files, alla voce Containers), il risultato dovrà essere più o meno così:
come si può osservare, l’area centrale della nostra main window è ora grigio scuro, questo perché è stata
inserita la MDIArea.
Autore P. Sereno http://www.sereno-online.com/site
4. Mini Guide Qt
Passo 3
Scriviamo ora nel file mainwindow.cpp il codice seguente:
#include "ui_mainwindow.h"
#include "mainwindow.h"
#include <QAction>
#include <QFileDialog>
#include <QImageReader>
#include <QList>
#include <QString>
#include <QLabel>
#include <QPixmap>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->actionOpen,SIGNAL(triggered()),this, SLOT(openFile()));
}
MainWindow::~MainWindow()
{
delete ui;
}
int MainWindow::openFile()
{
QString fileName,currentPath;
// set filters = all supported file formats. New plugins will automatically add
new image formats
QList <QByteArray> supportedFilters;
QString filters;
QString defaultFilter;
QImageReader reader;
supportedFilters = reader.supportedImageFormats();
defaultFilter.append(tr("Images ( "));
for (int i = 0; i < supportedFilters.size(); ++i)
{
defaultFilter.append("*.");
defaultFilter.append(supportedFilters[i].toUpper());
defaultFilter.append(" ");
filters.append(supportedFilters[i].toUpper());
filters.append(" (*.");
filters.append(supportedFilters[i]);
filters.append(" );;");
}
defaultFilter.append(");;");
filters.append(tr("Any File( * )"));
filters.prepend(defaultFilter);
fileName=QFileDialog::getOpenFileName(this,tr("Open"),currentPath,filters);
if (!fileName.isEmpty()) // if fileName is not empty
{
child = new QLabel(0);
child->setPixmap(fileName);
ui->mdiArea->addSubWindow(child);
child->show();
}
return 0;
}
Autore P. Sereno http://www.sereno-online.com/site
5. Mini Guide Qt
Passo 4
Analizziamo nel dettaglio ogni singolo metodo.
Il costruttore:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->actionOpen,SIGNAL(triggered()),this, SLOT(openFile()));
}
Fin qui nulla di nuovo rispetto la seconda lezione.
setupUI è il metodo incaricato di inizializzare l’intera interfaccia utente creata da Qt Creator.
connect realizza la connessione con la QAction di nome actionOpen del menu (File->Open) che abbiamo
creato da Qt Creator. Nella lezione 2 avevamo fatto una cosa analoga per la actionExit, ovvero il menu
responsabile di chiudere l’aplicazione; ora abbiamo creato un altro menu (File->Open) per l’apertura di un
file. Scopo della connect è “chiamare” un metodo in corrispondenza di un segnale generato dalla QAction;
questo metodo lo chiameremo openFile e sarà responsabile di aprire il nostro file immagine che andremo a
visualizzare.
Il distruttore:
MainWindow::~MainWindow()
{
delete ui;
}
Anche qui nulla di nuovo rispetto la lezione 2. Il distruttore si occupa di cancellare tutto ciò che era stato
creato in precedenza.
Il metodo int MainWindow::openFile():
Per prima cosa analizziamo le seguenti righe di codice:
QList <QByteArray> supportedFilters;
QString filters;
QString defaultFilter;
QImageReader reader;
supportedFilters = reader.supportedImageFormats();
Si tratta delle dichiarazioni necessarie per permettere successivamente alla nostra applicazione di
riconoscere quali sono i file immagine supportati (ad es PNG, JPG, BMP, etc...). Tutto si realizza attraverso la
Autore P. Sereno http://www.sereno-online.com/site
6. Mini Guide Qt
classe QImageReader che restituisce nella lista di ByteArray (cioè QList <QByteArray>) tutte le estensioni
dei files immagine riconosciuti. In altre parole, con la linea di codice
supportedFilters = reader.supportedImageFormats();
Andiamo a riempire la lista “supportedfilters” con tutte quelle estensioni di file che il nostro sistema può
leggere (cioè che le Qt sanno riconoscere grazie ai “decoder” di immagine installati).
Per approfondire questo argomento si può consultare la documentazione sul sito qtsoftware o il Qt
Assistant.
A questo punto, consideriamo il codice seguente:
for (int i = 0; i < supportedFilters.size(); ++i)
{
defaultFilter.append("*.");
defaultFilter.append(supportedFilters[i].toUpper());
defaultFilter.append(" ");
filters.append(supportedFilters[i].toUpper());
filters.append(" (*.");
filters.append(supportedFilters[i]);
filters.append(" );;");
}
si tratta di un ciclo for che itera sulla dimensione della lista “supportedfilters”. Questa lista infatti mette a
disposizione un elevato numero di metodi, tutti molto utili, tra cui il metodo size() che ci informa sul
numero di elementi contenuti nella lista.
Obiettivo del ciclo for è quello di creare una stringa (QString) contenente qualcosa del tipo: “*.PNG *.BMP
*.JPG” e così via. Questa strana stringa ci servirà nel resto del codice per filtrare (da qui il nome filter…)
quali files vogliamo andare ad aprire con la openFile.
Nota: le linee di codice di questo ciclo loop non devono essere considerate superficialmente, proviamo a
cambiare qualcosa (ad esempio a rimuovere l’istruzione filters.append(" );;"); e osservate cosa
succede.
Dopo il ciclo for concentriamoci ora su:
defaultFilter.append(");;");
filters.append(tr("Any File( * )"));
filters.prepend(defaultFilter);
fileName=QFileDialog::getOpenFileName(this,tr("Open"),currentPath,filters);
le prime 3 linee di codice servono per preparare la stringa filters da passare come parametro a QFileDialog
per selezionare solamente i files che ci interessa aprire (e cioè i files immagine supportati, ad esempio JPG,
BMP, PNG etc.)
Fermiamoci ora su:
fileName=QFileDialog::getOpenFileName(this,tr("Open"),currentPath,filters);
questa linea di codice è molto importante! Essa infatti ci permette di far comparire la dialog box standard di
apertura files illustrato in figura seguente:
Autore P. Sereno http://www.sereno-online.com/site
7. Mini Guide Qt
come si può osservare il campo Tipo File mostra l’indicazione
Images (*. BMP *.GIF *.ICO…
Questa è appunto la sequenza di filtri che abbiamo identificato grazie alle linee di codice che abbiamo visto
precedentemente.
Vediamo ora i parametri passati alla QFileDialog::getOpenFileName
tr("Open")
è il titolo della dialog box. Non si è scelto di scrivere direttamente la stringa (è cioè “Open”) ma si è voluto
passare attraverso il meccanismo della tr() per consentire la traduzione in lingue diverse dell’applicazione.
Può sembrare prematuro parlare subito di localizzazione, ma se ci abituiamo sin da subito a NON scrivere
direttamente le nostre stringhe nel codice ma le mettiamo sempre dentro ad una tr(), ci toveremo poi
pronti ad eseguire Qt Linguist (con lrelease/lupdate) per tradurre la nostra interfaccia utente. Per ora non ci
addentriamo nei dettagli della localizzazione, ma ricordiamoci di scrivere tutte le nostre stringhe dentro ad
una tr(). SEMPRE!
currentPath
questo parametro serve ad indicare quale path usare alla getOpenFileName per visualizzare i files.
Per questo esempio currentPath è stato dichiarato ma non usato. Lascio al lettore il compito di
inizializzarlo.
filters
è la nostra lista di filtri per la selezione del tipo di file da aprire
Autore P. Sereno http://www.sereno-online.com/site
8. Mini Guide Qt
Arriviamo ora all’ultimo blocco di istruzioni:
if (!fileName.isEmpty()) // if fileName is not empty
{
child = new QLabel(0);
child->setPixmap(fileName);
ui->mdiArea->addSubWindow(child);
child->show();
}
quando viene selezionato un file, la getOpenFileName restituisce in fileName una stringa (vuota nel caso di
nessun file selezionato).
L’istruzione:
if (!fileName.isEmpty())
serve appunto a verificare se un file è stato selezionato ed in tal caso si procede con il resto del codice,
altrimenti il metodo openFile termina senza caricare alcun file.
isEmpty() è uno dei tanti metodi della classe QString (i metodi sono molti e tutti utilissimi!) e serve per
sapere se la stringa è vuota.
Nel caso sia stato selezionato un file immagine verrà eseguito il codice seguente:
child = new QLabel(0);
child->setPixmap(fileName);
ui->mdiArea->addSubWindow(child);
child->show();
e qui dobbiamo soffermarci un po’ per capire.
child è una istanza di QLabel, classe molto utile per visualizzare qualsiasi cosa: da una semplice stringa ad
un’ immagine (che è proprio il nostro caso!)
La classe QLabel può visualizzare le immagini Pixmap; infatti il metodo setPixmap() ci consente proprio di
caricare un’immagine il cui “fileName” (cioè il path) è il parametro passato come argomento
(child->setPixmap(fileName);).
A questo punto dobbiamo indicare alla mdiArea che c’è una nuova subwindow da visualizzare e questro
viene fatto tramite la
ui->mdiArea->addSubWindow(child);
e per ultimo chiamiamo il metodo show() della QLabel ( child->show() ) per visualizzare la finestra child ed il
gioco è fatto.
Autore P. Sereno http://www.sereno-online.com/site
9. Mini Guide Qt
Considerazioni finali
Questa è la terza lezione di un ciclo che verrà reso disponibile gratuitamente in Internet sul sito
http://www.sereno-online.com/site
A partire da questa lezione le cose si fanno più complicate, servirà quindi più tempo per capirle e per fare sul codice
diverse prove.
Ogni vostro commento o richiesta di informazioni rappresenta un utile punto di partenza per nuove lezioni o
miglioramenti.
Buon divertimento!
Paolo
Autore P. Sereno http://www.sereno-online.com/site