Interfacce grafiche per i nostri programmi in GTK+ – parte 4 –

Adesso andremo a parlare di quegli oggetti base GTK+ utili all’utente per interagire con la nostra finestra o interfaccia GTK+.

Usare gli STOCK ITEM

Iniziamo con il parlare dei tasti già predefiniti ovvero quei tasti che hanno già di base un’icona al proprio interno ed hanno già definita l’operazione che deve essere compiuta in caso di pressione del tasto. Anche se a dire il vero la callback da eseguire alla pressione del tasto può essere anche cambiata, vediamo subito un esempio:

#include <gtk/gtk.h>

static void destroy (GtkWidget*, gpointer);
static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer);

int main (int argc, char *argv[])
{
/* Inizializzo i miei oggetti. */
GtkWidget *window, *button;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), “STOCK”);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 200, 100);
// Creiamo il tasto utilizzando la configurazione base per un tasto di chiusura della nostra finestra.
button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
// Connettiamo al segnale di clicked del tasto la chiamata alla funzione di distruzione della widget e gli passiamo come parametro la nostra finestra.
g_signal_connect_swapped (G_OBJECT (button), “clicked”, G_CALLBACK (gtk_widget_destroy), (gpointer) window);
gtk_container_add (GTK_CONTAINER (window), button);
g_signal_connect (G_OBJECT (window), “destroy”, G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), “delete_event”, G_CALLBACK (delete_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}

static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}


Il tutto dovrebbe risultare coma la Figura 1 qui sotto inserita:

Come si è già accennato in precedenza gli stock button non sono proprio legati alla callback che rappresentano dato che può essere cambiata in qualsiasi momento, ma ci saranno utili per avere già dei tasti pronti all’uso.

I Toggle Buttons

I toggle buttons sono degli oggetti widget che alla loro pressione cambiano lo stato da attivo in disattivo! In poche parole la pressione di un tasto implica lo stato attivo o non di un altro tasto e viceversa.
Proviamo il seguente programmino:

#include <gtk/gtk.h>

static void destroy (GtkWidget*, gpointer);
static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer);
// Funzione che gestirà lo stato attivo o disattivo del tasto a seconda del tasto premuto.
static void button_toggled (GtkToggleButton*, GtkWidget*);

int main (int argc, char *argv[])
{
/* Inizializzo i miei oggetti. */
GtkWidget *window, *vbox, *toggle1, *toggle2;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), “TOGGLE”);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 200, 100);
// Definiamo un vertical box come container per i nostri oggetti.
vbox = gtk_vbox_new (TRUE, 5);
// Creiamo i noostri toggle button con un tasto mnemoonico.
toggle1 = gtk_toggle_button_new_with_mnemonic (“_Attiva il tasto”);
toggle2 = gtk_toggle_button_new_with_mnemonic (“_Disattiva il tasto”);
// Aggiungiamo i nostri bottoni al nostro vertical box.
gtk_box_pack_start_defaults (GTK_BOX (vbox), toggle1);
gtk_box_pack_start_defaults (GTK_BOX (vbox), toggle2);
gtk_container_add (GTK_CONTAINER (window), vbox);
// Connettiamo i bottoni da noi creati alla nostra funzione di callback di toggled passandogli come parametro l’altro bottone.
g_signal_connect (G_OBJECT (toggle1), “toggled”, G_CALLBACK (button_toggled), (gpointer) toggle2);
g_signal_connect (G_OBJECT (toggle2), “toggled”, G_CALLBACK (button_toggled), (gpointer) toggle1);
g_signal_connect (G_OBJECT (window), “destroy”, G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), “delete_event”, G_CALLBACK (delete_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}

static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}

static void button_toggled (GtkToggleButton *toggle, GtkWidget *other_toggle)
{
// Se il tasto premuto e attivo cioè premuto.
if (gtk_toggle_button_get_active (toggle))
{
// Disattivo l’altro tasto, la sensibilità.
gtk_widget_set_sensitive (other_toggle, FALSE);
}else{
// Attivo il tasto, lo rendo sensibile alla pressione.
gtk_widget_set_sensitive (other_toggle, TRUE);
}
}


Il tutto dovrebbe risultare come in Figura 2:

Si possono impostare diversi flag nell’esempio si è usato quello sulla sensibilità di un tasto. Per gli altri flag si rimanda ad internet oppure a manuali specifici.

Check Buttons

In alternativa ai toggle buttons visti in precedenza, che a volte possono essere ingombranti è preferibile usare i check buttons, molto meno ingrombranti dei tasti, vediamo e commentiamo il seguente esempio.
Il tutto e  l’inizializzazione dei check buttons sono del tutto simili ai toggle buttons visti in precedenza:

#include <gtk/gtk.h>

static void destroy (GtkWidget*, gpointer);
static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer);
static void check_toggled (GtkToggleButton*, GtkWidget*);

int main (int argc, char *argv[])
{
// Definiamo il container window, un container vertical box tre tasti check buttons ed un tasto definito com stock item per la chiusura della nostra finestra.
GtkWidget *window, *vbox, *check1, *check2, *check3, *close;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), “CHECKBUTTONS”);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 300);
// Definiamo i nostri check buttons impostandogli pure una label.
check1 = gtk_check_button_new_with_label (“Opzione 1”);
check2 = gtk_check_button_new_with_label (“Opzione 2”);
check3 = gtk_check_button_new_with_label (“Opzione 3”);
// in questa maniera disabilito il check2 ed il check3.
gtk_widget_set_sensitive (check2, FALSE);
gtk_widget_set_sensitive (check3, FALSE);
// Connettiamo al nostro check2 il segnale di toggle (di spunta) e richiamiamo la callback check_toggled. Lo stesso vale per il check3.
g_signal_connect (G_OBJECT (check1), “toggled”, G_CALLBACK (check_toggled), (gpointer) check2);
g_signal_connect (G_OBJECT (check1), “toggled”, G_CALLBACK (check_toggled), (gpointer) check3);
// Tasto di chiusura definito come stock item.
close = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
g_signal_connect_swapped (G_OBJECT (close), “clicked”, G_CALLBACK (gtk_widget_destroy), (gpointer) window);
vbox = gtk_vbox_new (TRUE, 5);
gtk_box_pack_start (GTK_BOX (vbox), check1, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), check2, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), check3, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), close, FALSE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
// Connettiamo il segnale di destroy e delete event alla nostra window.
g_signal_connect (G_OBJECT (window), “destroy”, G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), “delete_event”, G_CALLBACK (delete_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}

static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}

// Funzione che gestisce il toggle (cambio di stato) dei nostri check1,2 e 3.
static void check_toggled (GtkToggleButton *A, GtkWidget *B)
{
// Se il nostro check è attivo…
if (gtk_toggle_button_get_active (A))
{
// …abilito anche l’altro check passato come g_pointer…
gtk_widget_set_sensitive (B, TRUE);
}else{
// …altrimenti lo disabilito.
gtk_widget_set_sensitive (B, FALSE);
}
}

Il tutto dovrebbe apparire come in Figura 3, dove abilitando il check1 attiveremo il check2 e il check3.  

I Radio Buttons

Un secondo tipo di widget derivato dai toggle buttons sono i radio buttons in effetti i radio buttons derivano, appunto, dai check buttons visti in precedenza.
Tutti i radio buttons lavorano a gruppi e solo un radio buttons può essere attivo (settato) in un gruppo di radio buttons.

Vediamo subito un esempio:

#include <gtk/gtk.h>

static void destroy (GtkWidget*, gpointer);
static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer);

int main (int argc, char *argv[])
{
// Definiamo la nostra classica finestra, un container del tipo vertical box, e quattro radio buttons.
GtkWidget *window, *vbox, *radio1, *radio2, *radio3, *radio4;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), “RADIOBUTTON”);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 200);
// Creiamo il nostro primo radio buttons, con una label a piacere e selezionato di default.
radio1 = gtk_radio_button_new_with_label (NULL, “PRIMO RADIO BUTTON”);
// Creiamo il radio button 2 che appartiene al gruppo del radio1 precedentemente definito.
radio2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1), “SECONDO”);
radio3 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1), “TERZO”);
// Eredita il gruppo definito in radio3. Quindi anche lui sarà del gruppo di radio1.
radio4 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio3), “QUARTO”);
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start_defaults (GTK_BOX (vbox), radio1);
gtk_box_pack_start_defaults (GTK_BOX (vbox), radio2);
gtk_box_pack_start_defaults (GTK_BOX (vbox), radio3);
gtk_box_pack_start_defaults (GTK_BOX (vbox), radio4);
gtk_container_add (GTK_CONTAINER (window), vbox);
g_signal_connect (G_OBJECT (window), “destroy”, G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), “delete_event”, G_CALLBACK (delete_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}

static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}

Il tutto dovrebbe risultare come in Figura 4:  

  Si faccia particolare attenzione che il primo radio buttons viene creato in una certa maniera, mentre il resto, utilizzando una funzione che oltre a definire una label vuole anche sapere a quale gruppo appartiene.

Text Entry

I widget text entry, sono degli oggetti che permettono l’inserimento di dati personali in una singola riga.
Questi possono essere usati anche per creare finestre di dialogo utili per l’inserimento di password o informazioni.

Di seguito creeremo una finestra nella quale verrà richiesta la password di un’utente e la password non sarà visibile, ma sarà nascosta da un carattere jolly.

#include <gtk/gtk.h>

static void destroy (GtkWidget*, gpointer);
static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer);

int main (int argc, char *argv[])
{
// Inizializziamo la nostra finestra un vertical ed un horizontal box due label ed infine il nostro entry.
GtkWidget *window, *vbox, *hbox, *label1, *label2, *entry;
gchar *str;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), “PASSWORD”);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 100);
// Concateniamo la stringa “Password per” con la nostra variabile d’ambiente che che contiene il nome dell’utente connesso. Il tutto poi messo nella nostra label.
str = g_strconcat (“Password per “, g_get_user_name(),”?”, NULL);
label1 = gtk_label_new (str);
label2 = gtk_label_new (“Password:”);
// Ed ecco qui la nostra entry. Settiamo il nostro carattere jolly oltre ad impostare la visibilità, cioè vedremo alla pressione della nostra password una serie di *.
entry = gtk_entry_new ();
gtk_entry_set_visibility (GTK_ENTRY (entry), NULL);
gtk_entry_set_invisible_char (GTK_ENTRY (entry), ‘*’);
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start_defaults (GTK_BOX (hbox), label2);
gtk_box_pack_start_defaults (GTK_BOX (hbox), entry);
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start_defaults (GTK_BOX (vbox), label1);
gtk_box_pack_start_defaults (GTK_BOX (vbox), hbox);
gtk_container_add (GTK_CONTAINER (window), vbox);
g_signal_connect (G_OBJECT (window), “destroy”, G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), “delete_event”, G_CALLBACK (delete_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}

static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}

Il tutto compilato darà come risultato la finestra di Figura 5:  

  Per tutti i text entry inoltre può essere settato l’editabilità del testo la possibilità di selezionarlo oltre ai comandi più comuni quali il copia incolla ed il taglia.

Spin Buttons

Gli spin buttons sono dei widget che permettono la selezione di valori numerici attraverso una barra con  tasti dedicati all’aumento ed alla diminuzione del valore impostato (oppure aumentare o diminuire il valore utilizzando i tasti di page up e page down), vediamo subito un esempio:

#include <gtk/gtk.h>

static void destroy (GtkWidget*, gpointer);
static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer);

int main (int argc, char *argv[])
{
// Inizializziamo i nostri oggetti quali lo spin per interi e per float oltre ad un vertical nox come layout..
GtkWidget *window, *spin_int, *spin_float, *vbox;
// Mentre qui inizializziamo le variabili che ci faranno da scala come di seguito descritto.
GtkAdjustment *integer, *float_pt;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), “SPINBUTTON”);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 100);
/* Per ADJUSTMENT abbiamo i seguenti valori, il valore di partenza, il valore minimo, il valore massimo, il passo di incremento, l’incremento al PgUP/DOWN e un valore inutile!!! */
integer = GTK_ADJUSTMENT (gtk_adjustment_new (5.0, 0.0, 10.0, 1.0, 2.0, 2.0));
float_pt = GTK_ADJUSTMENT (gtk_adjustment_new (0.5, 0.0, 1.0, 0.1, 0.5, 0.5));
/* Per settare un valore si utilizza il gtk_spin_button_set_value mentre per prelevare il valore impostato con gtk_spin_button_get_value, n.b. il tutto da provare. */
// Creiamo il nostro widget sia per l’intero che per il float.
spin_int = gtk_spin_button_new (integer, 1.0, 0);
spin_float = gtk_spin_button_new (float_pt, 0.1, 1);
vbox = gtk_vbox_new (TRUE, 5);
gtk_box_pack_start_defaults (GTK_BOX (vbox), spin_int);
gtk_box_pack_start_defaults (GTK_BOX (vbox), spin_float);
gtk_container_add (GTK_CONTAINER (window), vbox);
g_signal_connect (G_OBJECT (window), “destroy”, G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), “delete_event”, G_CALLBACK (delete_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}

static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}

Il tutto dovrebbe apparire come segue in Figura 6:  

Horizontal & Vertical Scales

Gli horizontal ed i vertical scales sono degli oggetti widget che a differenza degli spin sono graficamente degli slides. Inoltre non essendo degli spin limitiamo l’utente all’utilizzo delle barre impedendo a all’utente stesso di inserire un valore numerico.

Vediamo subito un esempio:

#include <gtk/gtk.h>

static void destroy (GtkWidget*, gpointer);
static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer);

int main (int argc, char *argv[])
{
/* Inizializzo i miei oggetti tra i quali un scale di interi ed uno float oltre ad un contenitore verticale. */
GtkWidget *window, *scale_in, *scale_float, *vbox;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), “SCALES”);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 200, 100);
/* Si setta il valore minimo, il valore massimo e il passo di avanzamento per lo scales orrizontale. */
scale_in = gtk_hscale_new_with_range (0.0, 10.0, 1.0);
/* Lo stesso per il float valore minimo, massimo e passo di avanzamento. */
scale_float = gtk_hscale_new_with_range (0.0, 1.0, 0.1);
/* Setto il decimale da visualizzare se zero visualizzo solo l’intero, se 1 visualizzo il tipo x.x e così via, 2 visualizzo x.xx etc. */
gtk_scale_set_digits (GTK_SCALE (scale_in), 0);
gtk_scale_set_digits (GTK_SCALE (scale_float), 1);
/* Posizione del valore che assume la barra allo spostamento. */
gtk_scale_set_value_pos (GTK_SCALE (scale_in), GTK_POS_RIGHT);
gtk_scale_set_value_pos (GTK_SCALE (scale_float), GTK_POS_LEFT);
/* gtk_range_get_value() per recuperare il valore della barra. */
vbox = gtk_vbox_new (TRUE, 5);
gtk_box_pack_start_defaults (GTK_BOX (vbox), scale_in);
gtk_box_pack_start_defaults (GTK_BOX (vbox), scale_float);
gtk_container_add (GTK_CONTAINER (window), vbox);
g_signal_connect (G_OBJECT (window), “destroy”, G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), “delete_event”, G_CALLBACK (delete_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}

static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}

Alla compilazione e di seguito all’esecuzione del nostro programma avremo il nostro scale come in Figura 7:  

  Il File Chooser Buttons

I file chooser button o meglio la finestra di dialogo che permette la selezione di una cartella o di un file permette appunto all’utente di selezionare con facilità un tipo di file oppure una cartella.
Il file chooser buttons è così un insieme di widget che permettono quello che è stato spiegato precedentemente, vediamo subito come realizzarlo ed impostarlo a seconda delle esigenze.   #include <gtk/gtk.h>

static void destroy (GtkWidget*, gpointer);
static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer);
//Funzione per il cambio cartella o dispositivo.
static void folder_changed (GtkFileChooser*, GtkFileChooser*);
//Funzione per il cambio/selezione del file.
static void file_changed (GtkFileChooser*, GtkLabel*);

int main (int argc, char *argv[])
{
/* Inizializzo i miei oggetti. Tra cui i nostri due selettori una etichetta ed infine il conteiner che conterrà i nostri oggetti widget. */
GtkWidget *window, *chooser1, *chooser2, *label, *vbox;
// Inizializziamo inoltre le nostre variabili che definirà i nostri filtri.
GtkFileFilter *filter1, *filter2;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), “FILECHOOSER”);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 400, 200);
// Creeremo la nostra label vuota.
label = gtk_label_new (“”);
//Box per la selezione della cartella o del dispositivo.
chooser1 = gtk_file_chooser_button_new (“Chooser a folder”, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
//Box per la selezione del file.
chooser2 = gtk_file_chooser_button_new (“Chooser a folder”, GTK_FILE_CHOOSER_ACTION_OPEN);
//Connetto il segnale di cambio selezione e gli passo come parametro la selezione del file.
g_signal_connect (G_OBJECT (chooser1), “selection_changed”, G_CALLBACK (folder_changed), (gpointer) chooser2);
//Connetto il segnale di selezione del file al segnale di cambio selezione e gli passo la label come parametro, che prenderà il nome del file selezionato.
g_signal_connect (G_OBJECT (chooser2), “selection_changed”, G_CALLBACK (file_changed), (gpointer) label);
//Setto la path di partenza per entrambe.
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser1), g_get_home_dir());
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser2), g_get_home_dir());
//Creiamo i filtri per i file.
filter1 = gtk_file_filter_new ();
filter2 = gtk_file_filter_new ();
//Definiamo il nome del gruppo dei filtri.
gtk_file_filter_set_name (filter1, “Image files”);
gtk_file_filter_set_name (filter2, “All files”);
//Estensione dei file da inserire nei gruppi.
gtk_file_filter_add_pattern (filter1, “*.jpg”);
gtk_file_filter_add_pattern (filter1, “*.png”);
gtk_file_filter_add_pattern (filter2, “*”);
//Aggiungo i filtri ai box di selezione.
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser2), filter1);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser1), filter2);
vbox = gtk_vbox_new (TRUE, 5);
gtk_box_pack_start_defaults (GTK_BOX (vbox), chooser1);
gtk_box_pack_start_defaults (GTK_BOX (vbox), chooser2);
gtk_box_pack_start_defaults (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (window), vbox);
g_signal_connect (G_OBJECT (window), “destroy”, G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), “delete_event”, G_CALLBACK (delete_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

static void destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit ();
}

static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}

static void folder_changed (GtkFileChooser *A, GtkFileChooser *B)
{
gchar *folder = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (A));
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (B), folder);
}

static void file_changed (GtkFileChooser *A, GtkLabel *B)
{
gchar *file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (A));
//Stampo la path completa compreso il nome del file.
gtk_label_set_text (B, file);
}   Se tutto è stato scritto e compilato correttamente il tutto dovrebbe dovrebbe apparire come in Figura 8:  

  In questo esempio abbiamo impostato due filtri uno globale assegnato al selettore relativo alla selezione del dispositivo mentre il secondo con il quale era solo possibile visualizzare e selezionare i file di tipo immagine.