GUI in Gtk+ con Glade & Anjuta
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

GUI in Gtk+ con Glade & Anjuta

on

  • 4,024 views

Attraverso un semplice esempio viene mostrato come utilizzare Glade e Anjuta per la realizzazione di GUI sfruttando la libreria grafica GTK e il linguaggio C.

Attraverso un semplice esempio viene mostrato come utilizzare Glade e Anjuta per la realizzazione di GUI sfruttando la libreria grafica GTK e il linguaggio C.

Statistics

Views

Total Views
4,024
Views on SlideShare
4,023
Embed Views
1

Actions

Likes
1
Downloads
125
Comments
0

1 Embed 1

http://www.slideshare.net 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-NonCommercial LicenseCC Attribution-NonCommercial License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

GUI in Gtk+ con Glade & Anjuta Document Transcript

  • 1. GUI in Gtk+ con Glade & Anjuta di Stefano Delfino
  • 2. Lo scopo di questa piccola guida è quello di mostrare come realizzare una semplicissima GUIutilizzando il linguaggio C e la libreria grafica Gtk+. La guida è stata realizzata utilizzando Ubuntu10.10 “Maverick Meerkat”. Potrebbero esserci delle lievi differenze tra le varie versioni ma in lineadi massima tutto dovrebbe corrispondere.1. InstallazionePer cominciare dobbiamo installare la libreria Gtk+ ed altre componenti neccessarie per il progetto.Installate i seguenti pacchetti assecondando tutte le dipendenze: • build-essential • libgtk2.0-dev • autotools-dev • libtool • intltool • intltool-debian • glade • anjutaOra abbiamo tutto ciò che ci serve per creare la nostra piccola GUI. Vogliamo creare una piccolainterfaccia di dialogo che ci permette di fare login mediante limmissione di username e password;il controllo delle credenziali inserite sarà fatto su un file di testo, ma noi siamo interessati soloallaspetto grafico e non alle varie tecniche di autenticazione degli utenti.Per prima cosa creiamo un dialogo di richiesta credenziali.Quella mostrata sopra è la nostra finestra di richiesta credenziali come viene mostrata in Glade afine lavoro. Di seguito viene mostrata la finestra di risposta allautenticazione avvenuta consuccesso.
  • 3. Immaginiamo uno scenario nel quale nella prima finestra inseriamo i dati di accesso e se sonocorretti apparirà la seconda finestra con su scritto lesito dellautenticazione positiva.Ora che abbiamo spiegato cosa vogliamo realizzare iniziamo vedendo i due strumenti principali cheandremo ad utilizzare.2. ToolsLa maggior parte del lavoro consiste nel disegnare la parte grafica. Per velocizzare questo processoesistono programmi per lo sviluppo rapido delle interfacce grafiche i cosiddetti RAD “RapidApplication Development”. Questi programmi permettono di disegnare linterfaccia grafica andandoa costruire la struttura gerarchica che tiene assieme i vari oggetti grafici; oltre a questo permettonoanche di impostare proprietà e comportamento dei vari componenti grafici. Per questa guidautilizzeremo Glade un programma RAD che ci permetterà di disegnare la nostra interfaccia grafica.Con questo programma andremo a strutturare le nostre due interfacce di dialogo componendo i varioggetti grafici. Il programma crea un file XML che contiene la struttura statica dellinterfaccia,elencando le componenti e le proprietà definite con Glade. Andiamo a vedere Glade come sipresenta graficamente.
  • 4. Ispettore Proprietà TavolozzaNotiamo varie parti in questo programma: una Tavolozza a sinistra, con le componenti chepossiamo trascinare allinterno della nostra GUI; un Ispettore in alto a destra, con la strutturagerarchica degli oggetti della nostra GUI, per il momento osserviamo che tra i widget vi è solo lafinestra “window” che andremo a creare nei passi successivi; un pannello Proprietà in basso adestra, sotto lispettore, con le proprietà degli oggetti che selezioniamo, attraverso il quale andremoa modificare dimensioni e caratteristiche delle componenti della nostra GUI.Laltro programma utilizzato in questa guida è Anjuta DevStudio un IDE “Integrated DevelopmentEnvironment” per applicazioni C/C++ e GNOME/Gtk+. Questo programma ci permette di creare egestire lintero progetto oltre a darci la possibilità di modificare linterfaccia grafica direttamente dalDesigner integrato.3. Concetti teoriciPrima di continuare bisogna introdurre un po di concetti teorici; verranno solo introdotti gli oggetti(grafici e non) che utilizzeremo ed è consigliato rileggere questa parte dopo aver completato la
  • 5. guida.Per la nostra GUI utilizzeremo loggetto grafico GtkWindow che ci permette di racchiudere al suointerno altri oggetti. I vari oggetti appartengono alla libreria Gtk e sono organizzati in una strutturagerarchica (potete cercare rapidamente e navigare allinterno della libreria tramite il programmaDevHelp “A developers help browser for GNOME”).In particolare distinguiamo diverse tipologie di oggetti:Containersoggetti contenitori che servono per contenere e dare struttura alle varie componenti; utilizzeremoper tale scopo tre differenti oggetti grafici contenitori, GtkVBox, GtkHBox, GtkHButtonBox.GtkVBox e GtkHBox servono per separare e contenere verticalmente e orizzontalmente i varioggetti, mentre GtkHButtonBox serve per contenere e separare orizzontalmente vari bottoni (percreare una pulsantiera).Controllo e Visualizzazioneoggetti utili per literazione con lutente. Tra questi utilizzeremo GtkLabel, GtkEntry, GtkButton.Oltre agli oggetti citati andremo ad utilizzare un oggetto non grafico GtkBuilder. Questo oggetto cipermette di descrivere uninterfaccia grafica tramite un file XML che definisce la User Interface. Inaltre parole a partire dal file XML, creato e modificato con Glade, è possibile creare uninterfacciache ci consente di comunicare con loggetto grafico rappresentante la nostra GUI.Segnali e gestori (callback)GTK è un toolkit guidato dagli eventi. La nostra GUI rimane in attesa, intrappolata allinterno delciclo gtk_main, che qualcosa accada. Quando si ha un evento, come la pressione di un bottone,verrà emesso il segnale appropriato dal componente grafico “widget” interessato. Per collegarequesto segnale ad unazione appropriata, dobbiamo predisporre un gestore che catturi il segnale o isegnali emessi e chiami la funzione corretta. Come vedremo questo viene fatto con listruzione:gint gtk_signal_connect ( Gtk_Object *object, gchar *name, GtkSignalFunc func, gpointer func_data );Listruzione riportata prende come primo argomento il widget che emetterà il segnale, comesecondo il nome del segnale che si vuole catturare, come terzo la funzione che verrà invocata pergestire il segnale, e come ultimo argomento i dati che sono passati al gestore.Il valore di ritorno di tipo gint è un identificativo di questo gestore. Come si può immaginare ognisegnale può essere gestito anche con più di una funzione; le funzioni di gestione diverse verrannoeseguite in sequenza. Tramite questo identificatore si ha la possibilità successivamente di rimuoverequesto gestore, e lo si fa tramite il comando:void gtk_signal_disconnect ( Gtk_Object *object,    gint id );Passando il widget da cui si vuole rimuovere il gestore di segnale e lidentificativo restituito da unadelle funzioni signal_connect, si può rimuovere il gestore di segnale che si desidera dal widget.Questa gestione dei segnali può essere fatta in modo rapido direttamente in Glade nella schedaSignals del pannello Propietà. Come vedremo più avanti basta definire solo la funzione di gestionenel nostro codice, affinché il collegamento segnale/funzione viene fatto in automatico.
  • 6. 4. Creiamo la nostra GUIIn questa parte alterneremo una sequenza di passi utilizzando i due programmi Anjuta e Glade alfine di realizzare la nostra interfaccia grafica.Anjuta: creiamo un nuovo progetto.Aprite il programma Anjuta, e create un nuovo progetto: • vi verrà richiesto che tipo di progetto volete creare, selezionate GTK+; • date un nome al progetto; • selezionate una destinazione per il progetto.Osserviamo che nella cartella di destinazione data, viene creato il progetto. Per poter lanciarequanto creato (cioè Execute dal menù run o semplicemente F3) bisogna prima configurare egenerare il progetto.Generiamo il progetto: • dal menù Build premi Build Project (opp. Maiusc+F7): viene richiesto di configurare il progetto. Lasciate la voce Configuration selezionata su Debug ed andate avanti premendo Execute; (NOTA: se non viene data la possibilità di eseguire Build Project è perché bisogna configurare il progetto manualmente tramite la voce Configure Project... sotto il menu Build) • verranno visualizzati dei messaggi, ed alla fine se tutto è andato correttamente viene visualizzato “Completed successfully”.Notiamo che è stata creata la cartella Debug. Ora lanciamo per la prima volta quanto creato al passoprecedente: • dal menù Run premi Execute (opp. F3); • apparirà una finestra di nome “window”, e osserviamo anche i messaggi nel Terminale dellIDE; • per il momento non preoccupiamoci del warning “Gtk-WARNING” tra poco lo andiamo a correggere.Ora che abbiamo visto per la prima volta la nostra finestra, andiamo a vedere anche dove si trovanellarea del progetto. In Anjuta, nel riquadro Files, andate a vedere nella cartella src; al suo internotroviamo diversi file, ma non tutti ci interessano, solo alcuni di questi verranno da noi modificati.Cominciamo a creare la nostra finestra di richiesta dati; premi con il tasto destro sul file *.ui eseleziona apri con Disegnatore di interfacce grafiche. Consiglio di non utilizzare il disegnatore“integrato” con Anjuta, ma quello separato installato e visto in precedenza; lo distinguiamo perchéquello separato si trova sotto la linea nel menù che appare. Se non lo trovate in questo menù èperché non vi è una associazione tra il file con estensione *.ui e il disegnatore di interfacce graficheGlade. Quindi possiamo aprirlo direttamente noi andando tramite Nautilus nella cartella /src delprogetto e premendo col tasto destro, apritelo con Glade. Se abbiamo seguito attentamente e citroviamo con quanto detto sopra vediamo apparire Glade con la nostra finestra già caricata.La figura mostrata in precedenza visualizza quanto detto; il rettangolo al centro è la nostra finestracreata in automatico nei passi precedenti. Andiamo a modificarla.Glade: modifica della finestra di richiesta credenzialiPer cominciare selezioniamo la finestra, possiamo farlo sia dallispettore che premendo sulloggettostesso.Nel pannello proprietà sotto la scheda General, andare a modificare i seguenti valori: • date un nome Name alla finestra, ad esempio “connectionWindow”;
  • 7. • impostare un titolo Window Title per la finestra, ad esempio “Autenticazione”; • impostare che la finestra non è ridimensionabile Resizable impostato su no; • impostare la Posizione nella quale la finestra deve apparire, mettere Centrato; • impostare una larghezza e altezza predefinita Default Width e Height: 350 x 220;Passate alla scheda Common ed impostare: • impostare una larghezza e altezza richiesta Request Width e Height: 350 x 220;Sotto la scheda Signals è possibile impostare i gestori per i segnali che vogliamo gestire; adesempio cosa vogliamo fare quando la finestra viene chiusa. La creazione automatica da parte delprogramma ha già provveduto per noi ad impostare il gestore destroy() per gestire la chiusuradella finestra; in pratica quando il segnale di distruzione della finestra destroy sotto la voceGtkObject viene emesso, viene intercettato dal gestore destroy() che troviamo dichiarato edefinito nei file callbacks.*.Se ricordiamo bene, la prima volta che abbiamo lanciato il programma, abbiamo riscontrato un“Gtk-WARNING” per via dellargomento NULL che di default viene passato al gestore;rimuovetelo in modo da non passare nulla al gestore del segnale. Se volete provate a salvare lemodifiche fatte con Glade e rilanciare da Anjuta il programma (F3) e vedete che il warning èscomparso. Basta semplicemente fare Execute (F3) che il Build (src) (F7) viene eseguito inautomatico. Noterete che al posto del warningGtk­WARNING   **:   Could   not   lookup   object   NULL   on   signal   destroy   of   object connectionWindowè comparso un altro messaggioGtk­CRITICAL **: gtk_widget_show: assertion `GTK_IS_WIDGET (widget) failedquesto perché abbiamo modificato il nome del oggetto finestra da “window” a“connectionWindow” in Glade; quindi andiamo a modificare nel main (per il momento solo questo)la lineawindow = GTK_WIDGET (gtk_builder_get_object (builder, "window"));inwindow = GTK_WIDGET (gtk_builder_get_object (builder, "connectioWindow"));Salvando e rilanciando (F3) il tutto notiamo che non ci sono più messaggi. Inoltre notate lemodifiche apportate e cioè la finestra posizionata centralmente, il nome, la dimensione e la nonridimensionabilità della stessa.Andiamo ad inserire altri componenti allinterno della finestra. • per prima cosa dobbiamo dividere lo spazio in parti orizzontali ne bastano 4; per fare ciò prendere loggetto Vertical Box (GtkVBox) nella parte “Containers” e metterlo allinterno della finestra, selezionare il numero di elementi desiderati Number of items su 4; • inserite nei due spazi centrali, due spazi verticali, andando quindi a trascinarvi una Horizontal Box (GtkHBox) e selezionando 2 elementi. Il risultato dovrebbe essere questo.
  • 8. Notate la selezione fatta e nellispettore sul GtkVBox e come è impostata la proprietàHomogeneous. Questa rende gli spazi uguali tra loro, e la impostiamo solo sugli spazi orizzontali enon su quelli verticali, perché andremo a modificare dinamicamente il contenuto del primo spazioorizzontale, da una Label con una sola riga di testo ad una con due righe.Inseriamo altri elementi. • prendere una Label (GtkLabel) nella parte “Control and Display” e posizionarla allinterno del primo spazio orizzontale; • modificate nome ed etichetta alla label, mettendo Name “connectionMessage” e Label “Inserisci le credenziali daccesso”; • sempre sulla label impostare Format label - justification a Center; • prendere una Horizontal Button Box (GtkHButtonBox) nella parte “Containers” e posizionarla allinterno dellultimo spazio orizzontale, e selezionare un numero di elementi pari a 1; • prendere un Button (GtkButton) nella parte “Control and Display” e posizionatelo allinterno dellunico “spazio bottone” della pulsantiera appena creata. • modificate nome ed etichetta del bottone, mettendo Name “connectionButton” e Label “Connetti”.Andiamo ora ad inserire la parte relativa alla Username ed alla Password. • Inserire due Label negli spazi verticali di sinistra e due Text Entry (GtkEntry) negli spazi di destra; • modificare la Label delle due Label: quella in alto “Username” e quella in basso “Password”; • modificate alcune proprietà delle TextEntry appena inserite, in particolare date nome “usernameEntry” e “passwordEntry” ed una Maxmum length pari a 30;
  • 9. • impostare nella TextEntry passwordEntry la Visibility su NO, questo per mascherare linput con il carattere inserito in Invisible character;Se provate a lanciare il programma noterete una leggera differenza tra le lunghezze delleTextEntry/Label corrispondenti; questo è dovuto alla lunghezza delle Label che cambia in base alproprio contenuto. Andiamo a migliorare questo aspetto estetico: • impostare la Width request sotto la scheda Common richiesta delle Label username e password a 100; • sotto la scheda Packing impostare Expand su NO.Ora se visualizziamo di nuovo la nostra finestra notiamo che il tutto compare più allineato edomogeneo.Prima di modificare anche i segnali impostati direttamente da Glade, andiamo a vedere un po ilcodice e a fare qualche modifica per collegare qualche segnale emesso dagli oggetti grafici.Anjuta: cominciamo a modificare il codiceQuello che segue è il codice del main.c così come generato alla creazione del progetto, eccetto cheper la modifica fatta al nome della finestra “connectionWindow”.#include <gtk/gtk.h>#include "callbacks.h" #define UI_FILE "src/tuorialgtk.ui"   GtkWidget* create_window (void) {  GtkWidget *window;  GtkBuilder *builder;  GError* error = NULL;  builder = gtk_builder_new ();  if (!gtk_builder_add_from_file (builder, UI_FILE, &error))  {  g_warning ("Couldnt load builder file: %s", error­>message);  g_error_free (error);  }  /* This is important */  gtk_builder_connect_signals (builder, NULL);  window = GTK_WIDGET (gtk_builder_get_object (builder, "connectionWindow")); 
  • 10.   g_object_unref (builder);    return window; } int main (int argc, char *argv[]) {   GtkWidget *window; #ifdef ENABLE_NLS  bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF­8");  textdomain (GETTEXT_PACKAGE); #endif  gtk_set_locale ();  gtk_init (&argc, &argv);  window = create_window ();  gtk_widget_show (window);  gtk_main ();  return 0; }Cercherò di commentare tutte le parti importanti di questo pezzo di codice.Per cominciare si include la libreria Gtk.#include <gtk/gtk.h>Allinterno del main la prima cosa che si fa è linizializzazione della libreria per poter utilizzare lecomponenti grafiche Gtk.gtk_init(&argc, &argv);Viene resa visibile la finestra creata.gtk_widget_show(window);Ed infine si entra nel ciclo principale con la funzione:gtk_main ();Da questo ciclo si esce quando viene chiamata la funzione gtk_main_quit() che viene chiamataautomaticamente con la chiusura della finestra (lo vediamo più avanti). Vediamo ora la funzionecreate_window().Osserviamo che in questa funzione facciamo uso della nostra finestra disegnata con Glade,UI_FILE definito sopra #define UI_FILE "src/tuorialgtk.ui". In particolare la utilizziamoutilizzando un oggetto di tipo GtkBuilder che da definizione è proprio una interfaccia per filetestuali come XML. GtkBuilder è un oggetto ausiliario che legge descrizioni testuali di unainterfaccia utente e istanzia loggetto descritto.I passi principali per riferirci ed utilizzare una interfaccia grafica descritta tramite un file XML sonoi seguenti:
  • 11. 1 ­ builder = gtk_builder_new ()2 ­ gtk_builder_add_from_file (builder, UI_FILE, &error)) 3 ­ gtk_builder_connect_signals (builder, NULL)4 ­ window = GTK_WIDGET (gtk_builder_get_object (builder, "connectionWindow"))5 ­ g_object_unref (builder)Per prima cosa si crea un GtkBuilder con il comando gtk_builder_new(); possiamo passare unadescrizione al GtkBuilder, tramite la funzione gtk_builder_add_from_file(). Un altro passoimportante è il collegamento con i segnali. Se nella parte grafica abbiamo dichiarato dei gestori dirisposta a segnali emessi dagli oggetti grafici, come ad esempio il nostro destroy(), per collegarlialle nostre funzioni di gestione scritte nei file callbacks.* dobbiamo chiamare un metodogtk_builder_connect_signal() che quindi mette in corrispondenza i gestori della descrizionecon i relativi gestori.builder = gtk_builder_new (); if (!gtk_builder_add_from_file (builder, UI_FILE, &error)) {  ...} /* This is important */ gtk_builder_connect_signals (builder, NULL);Per comprendere meglio limportanza di questo comando gtk_builder_connect_signal() provate a commentarlo e a lanciare il programma. Noterete che la finestra viene distrutta ma ilprogramma rimane nel ciclo gtk_main() questo avviene perché non vi è unassociazione tra ilsegnale emesso dalla finestra quando viene distrutta e la chiamata al nostro gestore destroy() equindi alla chiamata gtk_main_quit(). 1° viene premuto il bottone per chiudere la finestra.2° loggetto grafico connectionWindow ha dichiarato in Glade che vuole gestireil segnale destroy di GtkObject con il gestore destroy.3° viene cercato quindi un gestore destroy nel codice, questo grazie al comandogtk_builder_connect_signals(). 4° viene quindi eseguito il comando gtk_main_quit () che oltre a chiudere la finestra tramite il gestore delle finestre esce anche dal ciclo gtk_main ().void destroy (GtkWidget *widget, gpointer data) {  gtk_main_quit (); }Quella sopra riportata è la sequenza di passi eseguita se il comandogtk_builder_connect_signals() sarebbe decommentato. Quindi al momento di cercare ilgestore destroy() come dichiarato sul file XML *.ui tramite Glade lo si trova correttamente nelcodice eseguito. Mentre se il comando fosse commentato non vi sarebbe un collegamento tra igestori dei segnali dichiarati in Glade e le funzioni presenti nel programma e quindi non verrebbeeseguito il comando gtk_main_quit().Dopo aver fatto questa prova rimuovete il commento.Per rendere il programma più leggibile, rinominate il gestore destroy() in my_destroy() sia nei
  • 12. file callbacks.* e sia in Glade (sotto la linguetta Signals nelle Proprietà delloggettoconnectionWindow in corrispondenza del segnale GtkObject – destroy nella colonna Handler).Con la seguente chiamata è possibile prendere un puntatore ad un oggetto dellinterfaccia graficadisegnata.window = GTK_WIDGET (gtk_builder_get_object (builder, "connectionWindow"));In questo caso prendiamo un riferimento alla nostra finestra “connectionWindow”. Ultimoimportante passo è il comando:g_object_unref (builder);Con questultimo ci assicuriamo che quando le referenze a questo oggetto sono diventate nulle,loggetto viene rilasciato, cioè la memoria occupata viene liberata.Ora proviamo a collegare il nostro gestore rinominato in my_destroy() con il segnale emesso dalpulsante quando viene premuto. Per fare questo basta andare ad aggiungere nella funzionecreate_window() le seguenti istruzioni.{ ...GtkWidget *connectionButton;  ...  connectionButton = GTK_WIDGET (gtk_builder_get_object (builder,"connectionButton")); gtk_signal_connect (GTK_OBJECT (connectionButton), "clicked",                     GTK_SIGNAL_FUNC (my_destroy), NULL);  ...}Prendiamo un riferimento al bottone e colleghiamo tramite la funzione gtk_signal_connect(), ilsegnale emesso dal bottone quando viene premuto, al nostro gestore. Notate il cast a GTK_OBJECT (connectionButton), il segnale “clicked” emesso dal precedente oggetto, e il nome del gestorecon il relativo cast GTK_SIGNAL_FUNC (my_destroy). In questo modo la nostra finestra si chiuderàquando viene premuto il tasto “Connetti”. Salvate e lanciateil tutto e osservate se funziona.In questo esempio abbiamo visto come collegaredinamicamente con gtk_signal_connect()  un segnale alsuo gestore. Nota che era possibile farlo anche da Gladeandando a dichiarare my_destroy() come gestore perlevento clicked di GtkButton, come mostrato in figura, edomettendo quanto sopra.Ora andiamo a collegare levento “bottone premuto” ad ungestore che ci stampa nel terminale le credenziali inserite;questo per mostrare la creazione di un nuovo gestore e comereperire i dati inseriti.Per prima cosa dobbiamo aggiungere la dichiarazione edefinizione di un gestore che chiameremo check_data().
  • 13. // nel file callback.hvoid check_data (GtkWidget *widget, gpointer data);// nel file callbacks.cvoid check_data (GtkWidget *widget, gpointer data) { printf(“FACCIO QUALCOSA!! n”);}Una volta inserito il nostro nuovo gestore lo colleghiamo al segnale “clicked” del nostro bottone.// nel file main.cgtk_signal_connect (GTK_OBJECT (connectionButton), "clicked",                     GTK_SIGNAL_FUNC (check_data), NULL);Ora quando premiamo il bottone osserviamo la stampa nel Terminale.Per prendere il contenuto inserito nelle GtkEntry dobbiamo prendere dei riferimenti agli oggetti“usernameEntry” e “passwordEntry”. Per fare ciò abbiamo bisogno del nostro oggetto GtkBuilder.Possiamo procedere in diversi modi. Possiamo dichiarare il puntatore GtkBuider invece che nelmetodo create_window nel nostro main() o come variabile globale; dobbiamo inoltre stare attentiallistruzione g_object_unref(builder)  che renderebbe inutilizzabile la variabile. Ecco cosafaremo: • dichiariamo la variabile GtkBuilder *builder nel main; • spostiamo listruzione g_object_unref (builder)  alluscita dal gtk_main() quindi alla fine del nostro main(); • spostiamo listruzione builder = gtk_builder_new()  nel main prima della chiamata a create_window(); • passiamo il puntatore builder al metodo create_window (GtkBuilder *builder) {};Allinterno del gestore check_data() abbiamo bisogno del riferimento al nostro builder, percollegarci alla descrizione XML fatta con Glade e quindi prendere i riferimenti ai dati inseriti. Perfare ciò è possibile passare questo riferimento al nostro gestore al momento della connessione delsegnale con esso. Più precisamente quando utilizziamo gtk_signal_connect() nella funzionecreate_window().gtk_signal_connect (GTK_OBJECT (connectionButton), "clicked",                     GTK_SIGNAL_FUNC (check_data), builder);Il nostro gestore sarà quindi in grado di referenziale tramite loggetto GtkBuilder le nostre dueGtkEntry e prenderne il contenuto.void check_data (GtkWidget *widget, gpointer data) {  GtkWidget *username = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER(data),                                        "usernameEntry"));  GtkWidget *password = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER(data),                                        "passwordEntry"));    gchar *usernameInput = gtk_entry_get_text(GTK_ENTRY(username));  gchar *passwordInput = gtk_entry_get_text(GTK_ENTRY(password));   
  • 14. printf("Username: %s Password: %s n", usernameInput, passwordInput); }Nelle prime due istruzione vado a prendere i puntatori agli oggetti GtkEntry e nelle seguenti due nevado a prendere il contenuto testuale. Notate il cast fatto sulla variabile “data” da gpointer aGTK_BUILDER (NB: funziona anche senza cast).Andremo ora a simulare lautenticazione su un file di testo contente le credenziali di accesso. Createun file “account.txt” e posizionatelo nella stessa directory del progetto *.anjuta. Scrivete nel filealcune credenziali nella forma: username1 password1 username2 password2 ......FILE *fp;if ((fp = fopen("account.txt", "r")) == NULL) {  printf("ERRORE fopen R");  exit(1);  } char user[30]; char pass[30]; int trovato = 0;  while (fscanf(fp,"%s %s", user, pass) != EOF ) {  if ( (strcmp(user,usernameInput) == 0) && (strcmp(pass,passwordInput) == 0) ) {  printf(“AUTENTICATO n”); trovato = 1;   }} fclose(fp);if (trovato == 0) { printf(“NON AUTENTICATO n”);}Nel pezzo di codice riportato sopra si mostra la semplice gestione di un File testuale dalla sualettura al confronto con il testo Username e Password inseriti sopra. La variabile “trovato” cipermette di uscire appena viene trovata una corrispondenza allinterno del file. Possiamo inserirequesto codice allinterno del gestore check_data() subito dopo le due istruzionigtk_entry_get_text().Modifichiamo il codice per gestire il risultato dellautenticazione nella GUI.Se i dati inseriti non sono “corretti” modifichiamo la label “Inserisci le credenziali daccesso” in“ATTENZIONE!!nInserire i dati correttamente”, cancellando il testo inserito nelle due Entry. Diseguito le istruzioni da inserire al posto della stampa “NON AUTENTICATO”.GtkLabel *connectionMessage = GTK_LABEL(gtk_builder_get_object (GTK_BUILDER(data),                                        "connectionMessage")); gtk_label_set_text(connectionMessage,"Attenzione!!nInserire i dati correttamente");
  • 15. gtk_entry_set_text (GTK_ENTRY(gtk_builder_get_object (GTK_BUILDER(data),                              "usernameEntry")),""); gtk_entry_set_text (GTK_ENTRY(gtk_builder_get_object (GTK_BUILDER(data),                              "passwordEntry")),"");Per prima cosa, prendiamo il riferimento alla Label contenente il messaggio di intestazione dellafinestra, cioè “connectionMessage”, e poi ne modifichiamo il testo utilizzando la funzionegtk_label_set_text() e cancelliamo leventuale testo inserito con gtk_entry_set_text().A questo punto possiamo vedere lanciando il programma, che se i dati sono errati viene mostratauna label con un testo differente e vengono cancellati i dati inseriti. Mentre se i dati sono correttiviene stampato su terminale “AUTENTICATO” e viene ripresentata la finestra da capo. Noi aquesto punto vogliamo mostrare il risultato “AUTENTICATO” su unaltra finestra per comunicarloallutente. Per cominciare andiamo a creare la nuova finestra, disegnandola con Glade.Glade: creiamo la finestra risultatoAndando a modificare il nostro file *.ui, aggiungiamo una finestra. Basta premere sulloggettoWindow nella Tavolozza, tra i Toplevels. Poi: • date alla finestra le stesse proprietà della precedente: altezza e larghezza, posizione, ridimensionabilità; • dategli un nome “resultWindow” ed un titolo “Risultato”; • dichiarate il gestore “my_destroy” per la distruzione della finestra; • inserite allinterno della finestra una Label con nome “resultMessage” (letichetta non importa andiamo a modificarla prima di visualizzare la finestra); • sempre sulla label impostare Format label - justification a Center;Salvate il file con Glade e passiamo a modificare di nuovo il codice.Anjuta: collegare la finestra risultatoSe lautenticazione ha un esito positivo allora facciamo le seguenti cose: • settiamo la label della finestra di risultato dopo aver recuperato un riferimento ad essa; • visualizziamo la finestra risultato e nascondiamo quella di connessione.Quindi al posto dellistruzione printf(“AUTENTICATO n”) inseriamo le seguenti istruzioni.GtkWidget *resultWindow;resultWindow = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER(data), "resultWindow")); gtk_label_set_text(GTK_LABEL(gtk_builder_get_object (GTK_BUILDER(data),
  • 16.                              "resultMessage")),"Autenticazione OK"); gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER(data),                             "connectionWindow")));  gtk_widget_show (resultWindow);A questo punto abbiamo analizzato tutto il codice utile al nostro scopo. Di seguito si riportaintegralmente le parti significative del codice dei vari file.Main.c#include "callbacks.h"#define UI_FILE "src/tuorialgtk.ui"   GtkWidget* create_window (GtkBuilder *builder) {  GtkWidget *window;  GtkWidget *connectionButton;  GError* error = NULL;  if (!gtk_builder_add_from_file (builder, UI_FILE, &error))  {  g_warning ("Couldnt load builder file: %s", error­>message);  g_error_free (error);  }  /* This is important */  gtk_builder_connect_signals (builder, NULL);  window = GTK_WIDGET (gtk_builder_get_object (builder, "connectionWindow"));    connectionButton = GTK_WIDGET (gtk_builder_get_object (builder,                                  "connectionButton"));  gtk_signal_connect (GTK_OBJECT (connectionButton), "clicked",                            GTK_SIGNAL_FUNC (check_data), builder);    return window; } int main (int argc, char *argv[]) {   GtkWidget *window;  GtkBuilder *builder; #ifdef ENABLE_NLS  bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF­8");  textdomain (GETTEXT_PACKAGE); #endif  gtk_set_locale ();  gtk_init (&argc, &argv);  builder = gtk_builder_new ();    window = create_window (builder);  gtk_widget_show (window);  gtk_main ();    g_object_unref (builder);  return 0; }
  • 17. Callbacks.h#include <gtk/gtk.h> void my_destroy (GtkWidget *widget, gpointer data); void check_data (GtkWidget *widget, gpointer data);Callbacks.c#include "callbacks.h" #include <stdio.h> #include <stdlib.h> #include <string.h> void my_destroy (GtkWidget *widget, gpointer data) {  gtk_main_quit (); } void check_data (GtkWidget *widget, gpointer data) {  GtkWidget *resultWindow;  GtkWidget *username = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER(data),                                        "usernameEntry"));  GtkWidget *password = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER(data),                                        "passwordEntry"));    gchar *usernameInput = gtk_entry_get_text(GTK_ENTRY(username));  gchar *passwordInput = gtk_entry_get_text(GTK_ENTRY(password));  FILE *fp;    if ((fp = fopen("account.txt", "r")) == NULL) {  printf("ERRORE fopen R");  exit(1);  }  char user[30];  char pass[30];  int trovato = 0;    while ( fscanf(fp,"%s %s", user, pass) != EOF) {     if ( (strcmp(user,usernameInput) == 0) &&                   (strcmp(pass,passwordInput) == 0) ) {  resultWindow = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER(data),                        "resultWindow"));  gtk_label_set_text(GTK_LABEL(gtk_builder_get_object (GTK_BUILDER(data),                              "resultMessage")),"Autenticazione OK");    gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER(data),                              "connectionWindow")));   gtk_widget_show (resultWindow);  trovato = 1;     }  }  fclose(fp);  if (trovato == 0) { 
  • 18. GtkLabel *connectionMessage = GTK_LABEL(gtk_builder_get_object                                           (GTK_BUILDER(data), "connectionMessage"));  gtk_label_set_text(connectionMessage,"Attenzione!!nInserire i dati                                                                       correttamente");  gtk_entry_set_text (GTK_ENTRY(gtk_builder_get_object (GTK_BUILDER(data),                                           "usernameEntry")),"");  gtk_entry_set_text (GTK_ENTRY(gtk_builder_get_object (GTK_BUILDER(data),                                           "passwordEntry")),"");    } }RisorseImportanti risorse dove trovare altra documentazione sono: • http://www.micahcarrick.com/gtk-programming/ • http://library.gnome.org/devel/gtk-tutorial/stable/ • http://tadeboro.blogspot.com/2009/09/glade3-tutorial-1-introduction.html • http://www.hds619.net/blog/guida-gtk-a-puntate/ • http://anjuta.org/ • http://glade.gnome.org/