Ambienti e librerie grafiche per il C++ · Diagramma E-R descrivente in maniera semplificata il...

27
Scuola Politecnica e delle Scienze di Base Corso di Laurea in Ingegneria Informatica Elaborato finale in Programmazione I Ambienti e librerie grafiche per il C++ Anno Accademico 2014/2015 Candidato: Mario Napoletano matr. N46/1654

Transcript of Ambienti e librerie grafiche per il C++ · Diagramma E-R descrivente in maniera semplificata il...

Scuola Politecnica e delle Scienze di Base Corso di Laurea in Ingegneria Informatica Elaborato finale in Programmazione I

Ambienti e librerie grafiche per il C++

Anno Accademico 2014/2015 Candidato: Mario Napoletano matr. N46/1654

Alla mia famiglia e alla mia ragazza, che mi hanno su(o)pportato in questi anni

Indice

Indice .............................................................................................................................................. III

Introduzione ..................................................................................................................................... 4

Capitolo 1: Librerie e interfacce grafiche ........................................................................................ 6

1.1 Il modello ad eventi con delegati ........................................................................................... 7

1.2 I widgets, elementi costitutivi di un’interfaccia grafica ......................................................... 8

1.3 Librerie grafiche per il C++ ................................................................................................... 9

Capitolo 2: GIMP ToolKit (GTK+) ............................................................................................... 10

2.1 Architettura........................................................................................................................... 11

2.2 Hello World in GTK+ .......................................................................................................... 12

Capitolo 3: Allegro......................................................................................................................... 14

3.1 Hello World in Allegro ........................................................................................................ 15

Capitolo 4: Qt ................................................................................................................................. 16

4.1 Hello World in Qt ................................................................................................................. 17

Capitolo 5: Sviluppo di un esempio ............................................................................................... 19

5.1 Ambienti di sviluppo ............................................................................................................ 19

5.2 Visione concettuale .............................................................................................................. 20

5.3 Allegro ................................................................................................................................. 21

5.4 gtkmm .................................................................................................................................. 22

5.5 Qt .......................................................................................................................................... 23 5.6 Confronto ............................................................................................................................. 25

Conclusioni .................................................................................................................................... 26

Bibliografia .................................................................................................................................... 27

4

Introduzione

Nel presente lavoro di tesi si vanno a trattare, da un’ottica differente rispetto a quella cui

si è abituati nel percorso di studi universitario, le potenzialità del linguaggio di

programmazione C++: si intende porre l’attenzione sullo sviluppo di applicazioni

provviste di interfaccia grafica (GUI - Graphical User Interface), con le quali dunque

l’utente può comodamente e intuitivamente interagire.

Il C++ nasce ufficialmente nel 1983 da un’iniziativa di Bjarne Stourstrup nei laboratori

Bell allo scopo di integrare nel linguaggio di programmazione C la logica del paradigma

object-oriented.

Prendendo a modello il Simula (uno dei primi linguaggi orientati agli oggetti), il C with

classes – poi diventato C++ – introduce costrutti e concetti prima sconosciuti in un

linguaggio di programmazione, quale il C, in prevalenza procedurale, influenzato dal

Pascal e per particolari applicazioni avente corrispondenza 1:1 con codice assembly.

In particolare ricordiamo, per l’appunto, il concetto di classe, una sorta di contenitore di

proprietà ed azioni riconducibili ad una medesima entità, la quale, tipicamente,

corrisponde al modello di un’entità appartenente al dominio applicativo reale in cui il

sistema software è utilizzato; e poi ereditarietà e polimorfismo, che permettono di definire

gerarchie e proprietà comuni a più entità simili fra loro nel proprio contesto d’azione, in

modo da ridurre anche il numero di linee di codice ‘ripetitive’ in progetti che, per

applicazioni complesse, possono anche risultare di dimensioni molto estese, con relative

difficoltà di debugging e fault detection.

Volendo prendere in prestito il motto di Java, « write once, run everywhere » può

5

adattarsi anche a quello che è stato (e che prosegue tuttora, data la continua evoluzione

dei campi d’applicazione, e conseguentemente della complessità delle applicazioni

prodotte) lo sviluppo delle librerie software, vere e proprie ‘banche dati’ sfruttabili, ad

esempio, per l’interazione della propria applicazione con il sistema operativo o con i

dispositivi di I/O (di fatto loro scopo originario); esse rappresentano dei raccoglitori di

strutture dati e funzioni utili per particolari applicazioni (basti pensare alle librerie

OpenCV, per permettere specificamente lo sviluppo della cosiddetta computer vision e

l’interazione uomo-macchina) o anche, tendenza che è andata a incrementarsi

successivamente all’ideazione e standardizzazione del linguaggio C++, strutture dati e

funzioni per così dire general purpose: esempio particolarmente calzante è quello delle

Standard Template Libraries (STL), entrate a far parte a tutti gli effetti dello standard

ANSI/ISO nel 1995, che definiscono classi generiche (in particolare templates) e

particolari algoritmi di uso comune a un ampio spettro di applicazioni, così da permettere

di concentrare gli sforzi sullo sviluppo della logica applicativa.

Accanto alle librerie, possiamo prendere in considerazione la nascita degli ambienti

integrati di sviluppo (IDE – Integrated Development Environment), aventi il fine di

fornire strumenti per una programmazione più comoda, intuitiva e talvolta guidata, oltre

ad incapsulare le complesse e talvolta tediose operazioni di compilazione dei file sorgenti

e collegamento dei diversi file oggetto derivanti.

Conclusa questa panoramica storico-introduttiva, il presente lavoro di tesi si concentrerà

su come utilizzare le nozioni appena descritte al fine di sviluppare un’applicazione

grafica, andando a presentare alcune librerie nate allo scopo di creare interfacce grafiche e

a permettere l’interattività dell’utente con esse e, in più, facendone una sorta di confronto;

a tale scopo, si sono configurati diversi ambienti ciascuno con una diversa libreria, così da

fornire una trattazione quanto più ampia possibile.

Come caso di studio, è stato scelto lo sviluppo di un semplice videogame, il noto ‘Tic Tac

Toe’ (denominato anche ‘Tris’).

6

Capitolo 1: Librerie e interfacce grafiche

Da diverso tempo, l’utilizzo dei calcolatori è divenuto pervasivo nella vita di tutti i giorni

anche di chi non ha una conoscenza estesa del mondo informatico o non ne è coinvolto

dal punto di vista lavorativo o di studio. Per agevolare l’interfacciamento tra dispositivi

elettronici (nello specifico calcolatori) e utenti potenzialmente poco o per nulla esperti,

l’ideazione e realizzazione di interfacce grafiche permette di colmare quel gap che,

invece, l’interfaccia testuale (CLI – Command Line Interface) non può annullare se non

in minima parte, pur restando importante per diverse applicazioni.

Una libreria grafica fornisce una serie di componenti elementari per la costruzione di

interfacce grafiche; in che modo tali componenti vengano rappresentati ai fini

dell’elaborazione da parte delle unità di calcolo è celato al programmatore, che può

dunque vestire i panni del designer concentrandosi più sul realizzare applicazioni user-

friendly e sulla gestione delle interazioni uomo-macchina.

Progettare la composizione visiva e il comportamento di una GUI riveste una parte

importante all’interno dello sviluppo di un software, qualunque sia il target

dell’applicazione, dagli smartphone di ultima generazione ai touchscreens di musei e

stazioni, finanche ai sistemi embedded per applicazioni hard real-time safety-critical;

l’obiettivo di qualsiasi GUI è quello di migliorare l’efficienza e la semplicità nell’utilizzo

di un sistema software dal punto di vista dell’utente finale: l’usabilità rientra infatti a tutti

gli effetti tra i fattori di qualità di un software e la filosofia di progettazione centrata

sull’utente mira a risolvere nel modo migliore le problematiche d’interazione.

7

1.1 Il modello ad eventi con delegati

La presenza di un’interfaccia grafica all’interno di un’applicazione presuppone che lo

sviluppo che il programma segue nel corso della sua esecuzione è del tutto o in parte

subordinato agli input e in generale alle interazioni che l’utente ha con esso. Pertanto,

oltre a definire gli elementi costitutivi della GUI, le librerie grafiche si occupano anche di

fornire le metodologie attraverso le quali poter ‘sentire’ l’azione dell’utilizzatore e

definire i conseguenti comportamenti dell’applicazione.

L’approccio più adatto – e perciò più diffuso – è quello event-driven: questo paradigma

impone all’applicazione di essere sempre in ascolto di possibili eventi e di definire

porzioni di codice preposte alla gestione di tali eventi: i punti di ascolto sono spesso e

volentieri rappresentati dai widgets che compongono l’interfaccia, i quali recepiscono

l’evento e innescano l’esecuzione di quella che rappresenta, di fatto, una sorta di interrupt

service routine ad alto livello dedicata a quella specifica tipologia di evento. Possibili

eventi sono il click o il semplice passaggio del mouse, la pressione di un particolare tasto

su una tastiera, un doppio tocco su dispositivi con touchscreen, etc. Una visione

schematica di tale modello è proposta in Figura 1.

La gestione degli eventi avviene mediante listeners, ovvero delle entità di programma

associate ad una determinata sequenza di istruzioni che implementano la logica

dell’applicazione: una volta verificatosi l’evento, i listeners iscritti vengono notificati, e la

sequenza di istruzioni associata viene eseguita, mettendo in tal modo in piedi il

meccanismo tipico del pattern Observer.

A seconda del linguaggio di programmazione e della libreria grafica utilizzata, un listener

- Figura 1 -

Diagramma E-R descrivente in maniera semplificata il modello concettuale

8

può essere una funzione o un oggetto che esponga nella sua interfaccia i metodi necessari

affinché il collegamento tra il widget, cioè la sorgente dell’evento, e il gestore vero e

proprio (event handler) possa concretamente avvenire; i criteri e le modalità con cui tale

collegamento va messo in piedi sono definiti da ciascuna libreria grafica.

La tripla (sorgente, evento, gestore) rappresenta il modello ad eventi con delegati, dove

la sorgente corrisponde al componente grafico che ha acquisito l’interazione esterna,

l’evento è un oggetto o comunque un’entità descrittiva di tale interazione e il gestore è il

delegato a occuparsi d’implementare la business logic associata all’evento.

A livello architetturale, questo modello corrisponde di fatto al pattern Model-View-

Controller, in cui il Model corrisponde alla logica applicativa incapsulata dalla View,

grazie alla quale l’utente può visualizzare graficamente le parti salienti del Model,

manipolabili mediante il modulo Controller, corrispondente in pratica ai componenti

grafici pronti a raccogliere l’interazione, notificandola ai listeners (o observers, volendo

utilizzare la terminologia del design pattern fondamentale).

1.2 I widgets, elementi costitutivi di un’interfaccia grafica

Elementi fondamentali di un’interfaccia grafica sono i widgets, ossia dei componenti

messi a disposizione da una libreria grafica dalla cui costruzione e messa in relazione può

esser prodotto al meglio lo strato di presentazione del software: essi permettono all’utente

di interagire direttamente con l’applicazione, tramite lettura d’informazioni, selezione tra

opzioni e più in generale attraverso input per modificare e personalizzare l’esperienza

- Figura 2 -

Diagramma di sequenza che offre una visione dinamica del modello,

sfruttando come esempio il click di un bottone

9

d’uso. Ogni widget (termine nato come acronimo di window gadget) facilita una

particolare tipologia di interazione tra l’utente e il calcolatore e condivide con gli altri

componenti della GUI un dato tema, ovvero una veste grafica comune avente lo scopo di

farli aderire ad un medesimo design estetico, offrendo così coesione all’intera

presentazione del prodotto; inoltre, strutturare un’interfaccia grafica mediante widgets

permette da un lato agli sviluppatori di riusare oggetti aventi determinati compiti,

dall’altro agli utenti di sviluppare un’abitudine a determinate caratteristiche estetiche e

dimistichezza con un vocabolario comune alle diverse applicazioni che si troverà ad

utilizzare. Tra i vari widgets che si possono comunemente riscontrare annoveriamo

bottoni, finestre, etichette, caselle di testo, menu e anche immagini ed icone.

1.3 Librerie grafiche per il C++

Allegro Libreria software sviluppata in C/C++ orientata allo sviluppo di videogiochi

CGAL Libreria di algoritmi di geometria computazionale, utilizzata per il rendering

grafico di forme 2D/3D

FLTK Libreria orientata allo sviluppo di interfacce grafiche ‘snelle’

GTK+ Libreria grafica scritta in C orientata allo sviluppo di interfacce grafiche

OpenGL Libreria volta in particolare allo sviluppo di grafica tridimensionale

Qt Framework per lo sviluppo di applicazioni con interfaccia utente

wxWidgets Libreria grafica scritta in C++ orientata allo sviluppo di interfacce grafiche

Si è scelto di approfondire 3 di queste librerie, ciascuna delle quali differente dalle altre:

GTK+ è estremamente diffusa, in grado di donare alle applicazioni tratti grafici distintivi,

oltre ad essere molto utilizzata per le interfacce dei sistemi operativi Linux; Allegro è

pensata per lo sviluppo di videogames ed ha riscosso non poco successo in tale ambito; Qt

si presenta come un robusto framework, completo di IDE e graphic designer, estremamente

sfruttato per lo sviluppo di applicazioni sia in ambito open-source che commerciale.

10

Capitolo 2: GIMP ToolKit (GTK+)

Tra le librerie grafiche che hanno riscosso maggiori consensi per quanto riguarda la

creazione e gestione di interfacce grafiche, GIMP ToolKit (ben più conosciuta come

GTK+) s’impone come una delle più complete ed efficaci.

Come il nome del progetto indica, GTK+ nasce come libreria grafica di ausilio per lo

sviluppo del software di manipolazione di immagini GIMP (GNU Image Manipulation

Program) nei laboratori dell’università americana di Berkeley, dalle menti di Peter Mattis,

Spencer Kimball e Josh McDonald.

Dopo il rilascio di GIMP, lo sviluppo di GTK+ non si è fermato, ed è diventato parte

integrante del progetto GNU, condividendone pienamente la filosofia di dare vita a

software riusabile, ridistribuibile e modificabile in piena libertà: infatti, le librerie GTK+

sono rilasciate con licenza GNU LGPL, i cui termini ne permettono l’utilizzo per la

creazione di software sia liberi che proprietari o commerciali.

Benché nativamente pensato come integrazione alla piattaforma di gestione grafica X

Window System (tuttora standard de facto per i sistemi operativi Unix-like, Linux

incluso), è utilizzabile anche su Microsoft Windows e sul motore grafico di Mac OS X

Quartz, il che rende GTK+ una libreria grafica multipiattaforma, in grado di assicurare

elevata portabilità tra i vari sistemi operativi alle applicazioni realizzate basandosi sui

costrutti da essa definiti.

GTK+ è scritta in linguaggio C, esteso al paradigma object-oriented grazie alla libreria

GLib (e al sistema di emulazione di oggetti in essa incluso, GObject); ciononostante, è

possibile programmare mediante GTK+ anche in altri linguaggi, quali C++, JavaScript e

11

Python, grazie a un meccanismo di binding garantito dallo strato middleware

GObjectIntrospection, sfruttato dalle rispettive librerie d’interfacciamento gtkmm, Gjs (o

Seed) e PyGObject.

Su GTK+ si basano gli ambienti desktop GNOME (ambiente grafico utilizzato da diverse

versioni di Linux Ubuntu) e Xcfe (tipico di xUbuntu), oltre a numerose applicazioni, tra

cui il già citato editor di immagini GIMP, il web-browser Mozilla Firefox, il client di

posta elettronica Mozilla Thunderbird, i software di virtualizzazione della famiglia

VMware, l’editor di testo gedit e lo sniffer Wireshark.

2.1 Architettura

La libreria grafica GTK+ è strutturata in maniera modulare; ogni componente assolve uno

specifico compito ed è attivato all’occorrenza.

GLib è la libreria base, che interagisce direttamente con il sistema operativo su cui è

eseguita l’applicazione, astraendone le caratteristiche mediante tipi di dato wrapper che

assicurano la portabilità del codice su più piattaforme. Essa è responsabile della

definizione di strutture dati e procedure non strettamente legate alla grafica.

Cairo è la libreria utilizzata per la creazione di grafica vettoriale bidimensionale, sulla

quale si poggia di fatto il disegno vero e proprio dei vari elementi grafici

dell’applicazione sul display di riferimento.

GDK si occupa di incapsulare il sistema di gestione delle finestre e dei widgets della

piattaforma ospite, oltreché degli eventi dovuti alle interazioni dell’utente.

Pango è la libreria responsabile della resa testuale dell’applicazione, ivi compresa la

possibilità di internazionalizzazione del testo.

- Figura 3 -

Visione schematica dell’architettura GTK+

12

GIO si occupa di virtualizzare il file-system ospite e di fornire un’interfaccia standard

alle applicazioni GTK+ per le operazioni di I/O, anche su rete.

ATK è la libreria atta a predisporre l’applicazione affinché possa essere efficientemente

utilizzata anche dagli utenti con disabilità.

GTK+, infine, è lo strato più esterno, che si occupa di integrare tutti i componenti e di

comunicare direttamente con l’applicazione, offrendo interfacce per la programmazione

orientata agli oggetti; permette inoltre il caricamento dinamico della GUI, tramite il

GtkBuilder che può ricavarla da descrizioni in linguaggio XML, derivanti spesso e

volentieri da strumenti grafici di strutturazione di interfacce.

2.2 Hello World in GTK+

Di seguito si va a proporre un semplice esempio di utilizzo della libreria GTK+ per la

programmazione C++: a tal fine si fa uso dell’estensione gtkmm e della versione 3 della

libreria. Sono stati prodotti 3 file:

- helloworld.h : il nostro header

- helloworld.cpp : file sorgente contenente la definizione del costruttore e dell’handler

associato al click del mouse sul bottone

- main.cpp : file sorgente contenente la funzione main

/*** helloworld.h ***/

#ifndef HELLOWORLD_H

#define HELLOWORLD_H

#include <gtkmm/button.h>

#include <gtkmm/window.h>

/* la finestra principale eredita pubblicamente dalla classe Window definita nel namespace Gtk */ class HelloWorld : public Gtk::Window

{

public:

HelloWorld();

~HelloWorld(){};

protected:

void on_button_clicked(); // dichiarazione dell’handler da invocare

Gtk::Button button; // widget contenuto nella finestra (un solo bottone)

};

#endif

13

/*** helloworld.cpp ***/

#include "helloworld.h"

#include <iostream>

HelloWorld::HelloWorld() : button("Hello World") // creazione bottone con etichetta "Hello World" {

set_border_width(10);

// collegamento dell’handler all’evento click (eventi = segnali) button.signal_clicked().connect(sigc::mem_fun(*this,

&HelloWorld::on_button_clicked));

add(button); // aggiunta del bottone alla finestra

button.show(); // ora il bottone può essere mostrato

}

void HelloWorld::on_button_clicked()

{

std::cout<<"Hello world!"<<std::endl; }

/*** main.cpp ***/

#include "helloworld.h"

#include <gtkmm/application.h>

int main (int argc, char* argv[])

{

Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv,

"org.gtkmm.example"); // creazione dell’applicazione

HelloWorld hellowindow; // dichiarazione della finestra principale

return app->run(hellowindow); // esecuzione dell’applicazione

}

- Figura 4 -

Screenshot del programma in esecuzione su Ubuntu 15.10

14

Capitolo 3: Allegro

Un gran numero di applicazioni multimediali, ed in particolare videogames, che affollano

la rete sono realizzate usufruendo della libreria grafica Allegro.

Allegro (Allegro low level game routines) è una libreria grafica nata e sviluppata per

fornire supporto allo sviluppo di applicazioni videoludiche e multimediali in generale;

nata per iniziativa di Shawn Hargreaves negli anni ’90, in seguito ha coinvolto

sviluppatori di ogni nazionalità, riunitisi in un’unica community7 che tuttora contribuisce

aggiungendo funzionalità a una libreria open source ancora in crescita e pubblicando i

propri progetti corredati di codice sorgente.

La libreria si occupa di incapsulare la realizzazione di operazioni quali la creazione e

gestione delle finestre, il disegno e caricamento di immagini, l’ascolto e risposta agli

input dell’utente, la riproduzione di effetti sonori, e più in generale tutte quelle

operazioni di ‘basso livello’ (come rivela il nome della libreria) propedeutiche allo

sviluppo di applicazioni afferenti al mondo del multimedia. Il sito ufficiale della libreria6

si premura di specificare che Allegro non è un game-engine: ciò significa che tutto il

lavoro riguardante la logica del gioco, la progettazione grafica, lo schema che

l’interazione uomo-macchina deve seguire è demandato ai programmatori.

Caratteristica da rimarcare di Allegro è l’essere cross-platform, il che permette, per la

realizzazione delle routines di basso livello di cui sopra, di usufruire del medesimo

codice, utilizzabile per diverse piattaforme: Linux, Windows, MacOS X, iPhone,

Android (in via di sviluppo) e persino DOS (piattaforma nativa); Allegro risulta inoltre

estremamente modulare ed estensibile, in maniera tale da aggiungere funzionalità (ad

15

esempio un supporto alla grafica 3D mediante OpenGL o la gestione di diversi fonts) e

non solo, tant’è vero che la libreria è scritta in C / C++ ma è utilizzabile mediante

meccanismi di binding anche con altri linguaggi, come Python e .NET.

3.1 Hello World in Allegro

Per avere una fugace visione pratica della libreria, di seguito è proposto un esempio di

programma che mostra la scritta ‘Hello World!’. Si nota immediatamente la logica molto

legata al paradigma procedurale tipico del C, benché il linguaggio utilizzato sia a tutti gli

effetti il C++.

/*** helloworld.cpp ***/

#include <allegro5/allegro.h>

#include <allegro5/allegro_font.h> #include <allegro5/allegro_ttf.h>

int main(int argc, char* argv[]){

if(!al_init()) // inizializzazione di Allegro return -1;

al_init_font_addon(); // inizializzazione del componente aggiuntivo per il font al_init_ttf_addon(); // inizializzazione del componente aggiuntivo ttf

ALLEGRO_DISPLAY* display = al_create_display(640,480); // finestra principale if(!display) return -1;

ALLEGRO_FONT* font = al_load_ttf_font("Minimal.ttf",72,0); // caricamento del font if(!font)

return -1;

al_clear_to_color(al_map_rgb(0,0,152)); // sfondo blu al_draw_text(font, al_map_rgb(255,255,255), 640/2, 480/3, ALLEGRO_ALIGN_CENTRE, "Hello

World!"); // scrittura del testo

al_flip_display(); // la finestra è mostrata a video… al_rest(10.0); // …per 10 secondi al_destroy_display(display); // pulizia della memoria return 0;

}

- Figura 5 -

Screenshot del programma in esecuzione su Windows 8.1

16

Capitolo 4: Qt

Qt rappresenta uno dei framework maggiormente utilizzati per la realizzazione di

applicazioni, sia con che senza fini di lucro.

Rilasciata per la prima volta nel 1995 sotto l’egida della Trolltech, la libreria Qt è nata

dall’idea partorita da 2 sviluppatori, Haavard Nord ed Eirik Chambe-Eng, che hanno

pensato di realizzare un sistema di visualizzazione object-oriented. Qt è attualmente

sviluppata sia dalla Qt Company, sussidiaria della Digia, che ne detiene il copyright, sia

dalla community open-source Qt Project, ed è rilasciata sia in licenza commerciale che

open-source, a seconda del fine per il quale è sfruttata.

Più che una ‘semplice’ libreria grafica, Qt ingloba un insieme di softwares e tecnologie

aventi la finalità di garantire uno sviluppo di applicazioni quanto più completo ed

efficace possibile: risulta essere, infatti, un vero e proprio framework, all’interno del

quale sono compresi sia le librerie, sia l’IDE attraverso cui poterle utilizzare (Qt

Creator), sia un software di modellazione dell’interfaccia grafica (Qt Designer).

Come riportato dal sito ufficiale8, Qt è creata « da sviluppatori per sviluppatori » per

poter garantire un’esperienza di sviluppo comoda ed efficiente; la programmazione

tramite Qt permette di isolarsi dalla piattaforma di riferimento, essendo la libreria

multipiattaforma, con supporto anche per dispositivi mobili e sistemi embedded.

Sviluppata in C++, Qt mette a disposizione interfacce per l’utilizzo con altri linguaggi di

programmazone, quali Python e JavaScript (QML). Essa inoltre ‘estende’ il linguaggio

C++, mettendo a disposizione costrutti e parole chiave atti a fornire un livello di

astrazione ancora più alto (come ad esempio il meccanismo di signals e slots9 mediante il

17

quale si permette l’implementazione del pattern Observer): questo è reso possibile grazie

all’utilizzo del moc (metaobject compiler), un compilatore ‘intermedio’ che genera

codice aggiuntivo necessario ai fini della compilazione mediante il compilatore C++

tradizionale sottostante.

Grazie alle sue caratteristiche, il framework Qt è forse il più utilizzato per le applicazioni

commerciali e dalle grandi corporations dell’industria multimediale: alcuni esempi sono

Samsung, Walt Disney, Philips, Dreamworks, Electronic Arts, mentre tra le applicazioni

che utilizzano Qt per la propria interfaccia grafica si possono menzionare il riproduttore

multimediale VLC, Google Earth e Spotify per Linux. Anche l’Agenzia Spaziale

Europea ha scelto Qt per i propri softwares di modellazione e simulazione.

4.1 Hello World in Qt

Di seguito si mostra un esempio pratico di utilizzo della libreria: si realizza una semplice

applicazione che mostra un bottone recante la scritta ‘Hello World!’, cliccando il quale

viene mostrato un messaggio a video. Si sono prodotti 3 files: un header file per le

dichiarazioni necessarie (hellowindow.h) e 2 source files (hellowindow.cpp, che

implementa quanto dichiarato nell’header, e main.cpp).

/*** hellowindow.h ***/

#ifndef HELLOWINDOW_H

#define HELLOWINDOW_H

#include <QMainWindow>

namespace Ui {

class HelloWindow; }

class HelloWindow : public QMainWindow

{

Q_OBJECT // macro che verrà ‘scompattata’ dal metaobject compiler public:

HelloWindow(QWidget* parent = 0);

~HelloWindow();

private slots:

void on_pushButton_clicked(); // handler per la pressione del pulsante

private:

Ui::HelloWindow* ui; // user interface

};

#endif

18

/*** hellowindow.cpp ***/

#include "hellowindow.h"

#include "ui_hellowindow.h" // header autogenerato per l’interfaccia grafica #include <QMessageBox>

HelloWindow::HelloWindow(QWidget* parent) :

QMainWindow(parent),

ui(new Ui::HelloWindow)

{

ui->setupUi(this); /* l’interfaccia definita mediante Qt Designer viene automaticamente codificata in C++ */ }

HelloWindow::~HelloWindow()

{

delete ui; }

void HelloWindow::on_pushButton_clicked()

{

// creazione e visualizzazione del messaggio QMessageBox::information(this, “helloWorld”, “Hello World!”);

}

/*** main.cpp ***/

#include "hellowindow.h"

#include <QApplication>

int main(int argc, char* argv[]) {

QApplication a(argc, argv); // creazione dell’applicazione HelloWindow w; // creazione… w.show(); // …e visualizzazione della finestra

return a.exec(); // esecuzione dell’applicazione }

- Figura 6 -

Screenshot del programma in esecuzione su Windows 8.1

19

Capitolo 5: Sviluppo di un esempio

Come anticipato nel capitolo introduttivo, si va ora a porre l’accento sugli aspetti salienti

dello sviluppo del videogioco ‘Tic Tac Toe’, realizzato con ciascuna delle librerie

approfondite, e su un confronto fra queste.

5.1 Ambienti di sviluppo

Sono stati scelti 3 diversi IDE per portare avanti la programmazione. L’utilizzo di un IDE

risulta raccomandabile per incapsulare le operazioni di compilazione e linking, rese

complesse dalla presenza di queste librerie, non nativamente supportate dai compilatori

tradizionali (in particolare, nel caso di studio si è utilizzato il GCC), oltreché per poter

usufruire degli strumenti di ausilio alla programmazione che essi offrono.

Codelite è stato configurato per l’utilizzo di GTK+ (in particolare nella versione C++

gtkmm), operazione non molto complessa, in quanto l’ambiente permette la creazione

guidata di un progetto che fa uso di tale libreria grafica.

Code::Blocks è l’ambiente scelto per Allegro: questo IDE, oltre ad avere dei templates

già pronti, permette di definire le caratteristiche del proprio progetto, creando un wizard

ad hoc per le esigenze del programmatore.

Qt, come detto, si presenta già integrata nell’ambiente Qt Creator, il quale include anche

Qt Designer, utile ai fini della definizione per via grafica del layout e degli elementi che

costituiscono l’interfaccia; analogamente, per il progetto con gtkmm sono stati sfruttati i

file XML di descrizione prodotti dal software di modellazione Glade10

, caricati e

‘interpretati’ dinamicamente dall’applicazione.

20

5.2 Visione concettuale

A livello teorico, il gioco segue due fasi fondamentali: si sceglie il simbolo (X o O) del

giocatore iniziale, dopodiché ci si alterna nel porre i rispettivi simboli all’interno della

griglia di gioco: non appena uno dei giocatori riesce a mettere in fila tre suoi simboli,

guadagna un punto, la griglia viene ‘ripulita’ e si riparte con il perdente a cominciare per

primo, e così via finché uno dei due non raggiunge il punteggio massimo (in caso di parità

vige la regola dell’alternanza).

Pertanto l’applicazione è strutturata in due schermate fondamentali: la prima schermata

permette di selezionare il simbolo del Giocatore 1, il primo ad iniziare; la seconda,

mostrata a video solo a scelta avvenuta, presenta lo schema di gioco, la griglia in cui

verranno posti i simboli, ciascuno dei quali verrà disegnato nella cella in cui è stato

rilevato il click del mouse, nel rispetto del turno di gioco. Una volta disegnato il simbolo,

l’applicazione provvede a verificare se sono stati messi in fila (in diagonale, orizzontale o

verticale) tre simboli uguali: in caso negativo, la mano prosegue; altrimenti, appare un

- Figura 8 -

La schermata iniziale, ovvero un’immagine estremamente

semplice realizzata con il programma Paint

- Figura 7 -

Diagramma UML in cui si mostrano i macro-componenti che schematizzano il

comportamento dell’applicazione, indipendentemente dalla libreria

21

messaggio in cui si avvisa dell’avvenuto ‘tris’ e si mostra l’aggiornamento del punteggio.

Raggiunto il punteggio massimo, l’applicazione si congratula con il giocatore vincitore

per poi terminare.

5.3 Allegro

Allegro permette di tenere sotto controllo tutta la fase di inizializzazione delle

funzionalità offerte: dal nucleo della libreria al componente adibito alla gestione delle

immagini – punto forte della libreria – fino ai driver per la comunicazione con le

periferiche. Fondamentale per poter registrare le interazioni con l’utente è la creazione di

una ‘coda di eventi’ (ALLEGRO_EVENT_QUEUE) da popolare con le possibili sorgenti di

eventi che possono essere ad esempio la periferica mouse oppure il display: un

ALLEGRO_EVENT è una struttura dati che contiene tutte le informazioni riguardanti

l’evento registrato dalla piattaforma, codificando in un campo type la natura

dell’interazione, rispetto alla quale si possono valutare altri campi significativi.

Andando nello specifico, l’applicazione si mette in attesa di un ALLEGRO_EVENT di tipo

ALLEGRO_EVENT_MOUSE_BUTTON_DOWN, giunto il quale si può accedere al campo

mouse della struttura-evento e valutarne la posizione pixel-by-pixel: a seconda delle

coordinate x e y corrispondenti al click, il simbolo del Giocatore 1 sarà O oppure X.

Sullo stesso principio si basa poi la dinamica del gioco vero e proprio: viene caricata

l’immagine (ALLEGRO_BITMAP) della griglia e nella cella in cui giunge il click viene

mostrata l’immagine del simbolo corretto. Ogni ALLEGRO_BITMAP viene mostrata a

video solo all’invocazione della funzione al_flip_display(), grazie alla quale tutte le

elaborazioni riguardanti gli aspetti grafici che stanno avvenendo ‘alle spalle’ di quanto è

in quel momento mostrato a video terminano e il risultato può essere visualizzato.

Dall’utilizzo della libreria Allegro si nota subito la logica estremamente procedurale che

essa tende a far mantenere al programmatore; naturalmente nulla vieterebbe di

‘incapsulare’ le diverse funzioni all’interno di un approccio object-oriented, la cui

corretta gestione cadrebbe in toto nelle responsabilità del programmatore. D’altronde il

fine che la libreria si pone, ovvero fornire ‘procedure di basso livello’, non metodologie

22

d’alto livello o classi di cui usufruire, è abbastanza chiaro sin dall’acronimo ricorsivo

della libreria (Allegro low level game routines).

5.4 gtkmm

La programmazione tramite gtkmm permette di utilizzare nativamente tutti quei

meccanismi coi quali si è imposto il C++: ereditarietà, polimorfismo, namespaces, etc.

La prima schermata è stata progettata in Glade sotto forma di una Gtk::Image, inclusa

all’interno di un Gtk::EventBox per poter registrare il click del mouse, che invece

l’immagine da sola non avrebbe potuto ricevere. A livello di codice, per potersi legare

all’interfaccia volendo aggiungere comportamenti e proprietà aggiuntive ai widgets che la

compongono è necessario ottenere un riferimento al file XML (formato .glade) da salvare

all’interno di un Glib::RefPtr<Gtk::Builder> che viene poi sfruttato per legarsi agli

oggetti dell’interfaccia a runtime, tramite gli id assegnatigli in fase di progettazione. La

libreria GLib appena vista è estremamente utile per le classi e i metodi che permette di

utilizzare, come il RefPtr<>, uno smart pointer auto-distruttivo, o la classe ustring, che

permette un utilizzo efficiente delle stringhe in standard UTF. Nello specifico del nostro

‘Tic Tac Toe’, si è derivata la classe Gtk::EventBox in una classe EventBoxSimb allo

scopo di ridefinire l’handler associato al click, scrivendo all’interno di esso le istruzioni

necessarie per il salvataggio della scelta dei simboli.

La seconda schermata che viene visualizzata presenta un layout ‘a griglia’, dunque

predisponendo già lo scheletro dello schema di gioco; ciascuna cella della griglia 3x3

presenta una Gtk::DrawingArea, un particolare widget in cui è possibile effettuare

disegni di forme geometriche più o meno complesse a tempo di esecuzione: ciò è

possibile grazie a Cairo, una libreria orientata alla grafica vettoriale inclusa nella ‘macro-

libreria’ GTK+ (e dunque in gtkmm) della quale si è usufruito per il disegno dei simboli.

Lo schema che si è implementato in poche parole è il seguente: all’avvio della seconda

schermata, indipendentemente da turni o clicks, l’applicazione disegna la griglia di gioco;

cliccata una cella vuota, si attiva quella specifica ‘area di disegno’, viene resa vera una

speciale condizione logica e viene inviato il segnale di draw (queue_draw()), il cui

23

handler stavolta sarà autorizzato a disegnare il simbolo corrispondente al turno corrente.

Quanto era realizzato in Allegro con un paradigma procedurale, in gtkmm è stato

facilmente ‘tramutato’ in object orientation: a testimonianza di questo, mentre in Allegro

tutte le condizioni e le variabili necessarie per il proseguimento del gioco sono gestite dal

main, il progetto in gtkmm è provvisto di una classe GamePlayController, che si

occupa di gestire tutto il necessario, dalla matrice su cui le funzioni interne

all’applicazione eseguono le elaborazioni alle variabili di gestione dei turni, fino al

metodo di fine gioco; si è scelto di implementare il controller secondo il pattern

Singleton, per far sì che ne esista una e una sola istanza con più punti d’invocazione

all’interno del codice. Inoltre gtkmm incapsula diverse operazioni, quali il continuo ciclo

di attesa di eventi e relative inizializzazioni, tutte incluse nella creazione di una

Gtk::Window (magari prelevandola dal file di design) e di una Gtk::Application, di cui

invocare il metodo run(), passandogli la finestra da visualizzare.

5.5 Qt

La scrittura dell’applicazione mediante Qt si è rivelata rapida e intuitiva: a renderla tale

ha contribuito l’integrazione totale tra libreria e ambiente di sviluppo, che offre una facile

creazione di un progetto con annessa interfaccia grafica, la quale può essere manipolata

graficamente mediante Qt Designer, anch’esso incorporato nell’ambiente.

Gran parte della logica applicativa è stata riportata pari pari dall’applicazione scritta

secondo gtkmm - essendo entrambe incentrate sull’utilizzo di un paradigma ad oggetti -

salvo naturalmente effettuare i robusti accorgimenti necessari per adattarsi alla diversa

libreria. Anche in Qt, si è sfruttata l’ereditarietà per aggiungere comportamenti e

proprietà ai widgets definiti nel designer, col quale il legame risulta più automatico agli

occhi del programmatore: l’interfaccia, codificata in XML (formato .ui), viene tradotta in

C++, facendo diventare le strutture XML classi e variabili membro e producendo i files

d’intestazione e oggetto necessari; un puntatore alla classe-interfaccia compilata

automaticamente è memorizzato all’interno della corrispondente classe in cui poter

esplicitare i comportamenti dinamici che le si vuole assegnare, quali le operazioni da

24

svolgere in caso di click e di ridisegno della griglia e dei simboli. Nell’applicazione, la

classe SimbArea (ovvero la cella del layout a griglia) istanzia un oggetto QPainter,

adibito alla realizzazione di grafica vettoriale, il quale provvede a disegnare lo schema di

gioco e, se la condizione logica ad hoc è stata resa vera dal click, anche il simbolo del

giocatore che ha il turno in tale momento.

Nella descrizione fatta nel Capitolo 4, si è osservato che Qt prevede un compilatore

‘intermedio’, il moc; esso viene sfruttato per ‘spacchettare’ parole-chiave, introdotte

nell’ambiente per aumentare la semantica e la comprensione del codice, non riconosciute

dal compilatore GCC; tra queste nell’applicazione si è fatto uso della ‘dichiarazione’

Q_DECL_OVERRIDE, con la quale si specifica che il metodo cui si riferisce è soggetto a

override, di Q_OBJECT, già mostrata nell’esempio al paragrafo 4.1, e della parola-chiave

emit, avente l’unico scopo di precedere l’invocazione di un metodo che farà scaturire uno

o più segnali, e dunque modifiche alla resa grafica dell’applicazione: in particolare, emit

è stata utilizzata insieme ad update() per permettere il disegno del simbolo a seguito del

click da parte dell’utente.

Analogamente a gtkmm, Qt offre classi rivelatesi utili per la scrittura dell’applicazione,

quali QApplication (simile a Gtk::Application), QString (simile a Glib::ustring) e il

container QList<> (simile ai contenitori STL).

- Figura 9 -

Un confronto tra le diverse rese grafiche di una medesima situazione di gioco.

Da sinistra a destra: Qt su Windows 8.1, Allegro su Windows 8.1 e gtkmm su Ubuntu 15.10

25

5.6 Confronto

Ci si appresta a proporre una tabella riepilogativo-comparativa, affinché possano esser

messi in luce differenze, peculiarità e punti di contatto delle librerie grafiche con le quali

si è avuto modo di cimentarsi.

- Tabella riepilogativa -

Caratteristiche Allegro gtkmm Qt Portabilità del codice

Documentazione

Semplicità di configurazione

Definizione grafica dell'interfaccia

Ausilio alla programmazione

Facilità di utilizzo

Resa grafica

Una volta concluso il periodo di training necessario per una corretta comprensione delle

funzionalità offerte, coadiuvato dalle esaustive documentazioni reperibili nei rispettivi siti

ufficiali, ciascuna libreria si presenta relativamente semplice da utilizzare, oltreché

portabile su diverse piattaforme, come si è descritto nei capitoli dedicati.

Tuttavia, Allegro necessita un minore sforzo di comprensione iniziale, non avendo una

grande complessità, e perlopiù lasciando libertà di implementazione agli sviluppatori: in

virtù di questa prerogativa, risulta spiegata la pochezza di strumenti di ausilio alla

programmazione, sui quali invece si concentrano gtkmm e in modo particolare Qt,

mettendo a disposizione strutture dati utili per l’interazione con la piattaforma grafica.

Per quanto detto nei capitoli precedenti, Qt è un ambiente di sviluppo con la libreria

completamente integrata, il che azzera di fatto le operazioni di configurazione, e con la

possibilità di definire graficamente l’interfaccia dell’applicazione, attuabile anche con

gtkmm, libreria mediante la quale è sembrato possibile produrre una grafica più

accattivante e piacevole agli occhi dell’utente finale.

26

Conclusioni

Con l’elaborato appena presentato si è cercato di mostrare l’ampia potenzialità e

diffusione che il C++ continua a preservare - nonostante lo sviluppo e diffusione di

linguaggi di programmazione più ‘di alto livello’ e intuitivi (si pensi a Java o Python) -

anche per applicazioni moderne e persino ludiche come quella che ci si è impegnati a

realizzare da zero.

Considerata l’ampia gamma di librerie grafiche per C++ esistenti, l’utilizzo dell’una

piuttosto che dell’altra è estremamente vincolato al giudizio di chi andrà a progettare e/o

sviluppare l’applicazione e al suo scopo d’uso: se si desidera un’applicazione con

un’interfaccia grafica il meno invasiva possibile, si può scegliere ad esempio FLTK (non

approfondita in quest’elaborato); se si è alla ricerca di una libreria completa di strumenti

per la produzione di una grafica complessa, utile sia per progetti semplici/didattici che per

applicazioni di una certa entità, GTK+ rappresenta una scelta consona, così come Qt, che

porta con sé l’idea di un intero framework al servizio delle esigenze di sviluppo; Allegro

risulta invece ideale per chi intende creare in particolar modo videogames, conservando

estrema libertà di integrazione con altri componenti o per chi è più legato a un approccio

procedurale piuttosto che object-oriented e desidera una libreria che si occupi soltanto

della gestione di finestre, immagini e interazioni, senza ulteriori strumenti e appoggi.

27

Bibliografia

[1] The C++ Resources Network, http://www.cplusplus.com/info/history/, 14/12/15

[2] The Linux Information Project, http://www.linfo.org/widget.html, 14/12/15

[3] The GTK+ Project, http://www.gtk.org/, 17/12/15

[4] GTK+ Overview, https://developer.gnome.org/gtk3/stable/gtk.html, 18/12/15

[5] gtkmm – C++ Interfaces for GTK+ and GNOME, http://www.gtkmm.org/, 04/01/16

[6] Allegro – Introduction, http://liballeg.org/readme.html, 22/12/15

[7] Community ufficiale di Allegro, https://www.allegro.cc/about, 22/12/15

[8] Qt – Home, http://www.qt.io/, 23/12/15

[9] Signals & Slots, http://doc.qt.io/qt-5/signalsandslots.html, 23/12/15

[10] Glade – A User Interface Designer, https://glade.gnome.org/, 04/01/16

[11] Allegro 5.0 reference manual, https://www.allegro.cc/manual/5/, 05/01/16

[12] Programming with gtkmm 3, https://developer.gnome.org/gtkmm-tutorial/stable/,

05/01/16

[13] gtkmm Reference Manual, https://developer.gnome.org/gtkmm/stable/, 05/01/16

[14] Qt Documentation, http://doc.qt.io/qt-4.8/index.html, 05/01/16