Avanti Indietro Indice

3. Proseguiamo

3.1 Tipi di Dato

Ci sono alcune cose che avrete probabilmente notato nei precedenti esempi che hanno bisogno di una spiegazione. I gint, gchar ecc. che vedete sono tipi di dato (typedef) riferiti rispettivamente a int e char. Questo viene fatto per rimediare alle scomode dipendenze dalle dimensioni di semplici tipi di dato quando si fanno dei calcoli. Un buon esempio è ``gint32'' il quale sarà un tipo di dato riferito ad un intero a 32 bit per tutte le piattaforme, sia per gli x86 che per gli per gli alpha a 64 bit. I tipi di dato sono ben spiegati più avanti e molto intuitivi. Sono definiti in glib/glib.h (il quale viene incluso da gtk.h).

Noterete anche la possibilità di utilizzare un GtkWidget quando la funzione richiede un GtkObject. GTK è una libreria orienta agli oggetti ed un widget è un oggetto.

3.2 Altri Dettagli sui Segnali

Diamo un'altra occhiata alla dichiarazione della funzione gtk_signal_connect.

gint gtk_signal_connect (GtkObject *object, gchar *name,
                         GtkSignalFunc func, gpointer func_data);
Notate il valore di ritorno definito come gint? Questo è un identificatore per la vostra funzione di callback. Come detto sopra, si possono avere più funzioni di ritorno per ogni segnale e per ogni ogetto a seconda delle necessità, ed ognuna sarà eseguita in sequenza, nell'ordine in cui è stata collegata.

Questo identificatore vi permette di rimuovere una funzione dalla lista delle funzioni di ritorno tramite la seguente chiamata

void gtk_signal_disconnect (GtkObject *object,
                            gint id);
Così, passando il widget da cui si vuole rimuovere il gestore di segnale e l'identificativo restituito da una delle funzioni signal_connect, si può rimuovere il gestore di segnale che si desidera dal widget.

Un'altra funzione, usata per rimuovere tutti i segnali di un widget in una volta sola è:

gtk_signal_handlers_destroy (GtkObject *object);

Questa chiamata è abbastanza auto esplicativa. Semplicemente rimuove tutti i segnali collegati al widget che si passa alla funzione come argomento.

3.3 Miglioriamo Hello World

Diamo un'occhiata ad una versione migliorata di Hello World con altri esempi sulle callback. Questo ci introdurrà anche al nostro prossimo argomento, l'impacchettamento dei widget.

/* helloworld2.c */
#include <gtk/gtk.h>

/* La nostra funzione di callback migliorata. I dati passati a questa
 * vengono stampati su stdout. */
void callback (GtkWidget *widget, gpointer data)
{
    g_print ("Hello again - %s was pressed\n", (char *) data);
}

/* Un'altra callback */
void delete_event (GtkWidget *widget, gpointer data)
{
    gtk_main_quit ();
}

int main (int argc, char *argv[])
{
    /* GtkWidget e' il tipo di dato per i widget */
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *box1;

    /* Questa funzione e' invocata in tutte le applicazioni GTK, gli 
       argomenti sono analizzati e restituiti all'applicazione. */
    gtk_init (&argc, &argv);

    /* Crea una nuova finestra */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    /* Questa e' una nuova chiamata. Assegna "Hello Buttons" come titolo 
       della nostra finestra */
    gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");

    /* Qui settiamo il gestore per il segnale "delete_event" che
       immediatamente esce dalla applicazione.
    gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                        GTK_SIGNAL_FUNC (delete_event), NULL);


    /* predispone il bordo della finestra */
    gtk_container_border_width (GTK_CONTAINER (window), 10);

    /* creiamo una scatola dove mettere tutti i widget. Questa è descritta
       dettagliatamente nella sezione "packing". La scatola non è realmente
       visibile, è solamente usata per sistemare i widget. */
    box1 = gtk_hbox_new(FALSE, 0);

    /* Inseriamo la scatola nella finestra */
    gtk_container_add (GTK_CONTAINER (window), box1);

    /* Creiamo un nuovo bottone con etichetta "Button 1" */
    button = gtk_button_new_with_label ("Button 1");

    /* Quando il bottone e' premuto, noi invocheremo la funzione di callback,
       con un puntatore alla stringa "button 1" come proprio argomento) */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
                        GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");

    /* invece di aggiungerlo alla finestra, lo inseriamo nella scatola invisibile,
       la quale e' stata inserita nella finstra. */
    gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);

    /* Ricordati sempre questo passo. Dice a GTK che la preparazione di questo 
       bottone e' finita e che quindi puo' essere mostrato. */
    gtk_widget_show(button);

    /* Facciamo la stessa cosa per il secondo bottone. */
    button = gtk_button_new_with_label ("Button 2");

    /* Chiamiamo la stessa funzione ma passandogli un argomento differente,
       gli passiamo un puntatore alla stringa "button 2" */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
                        GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");

    gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);

    /* L'ordine nel quale i bottoni sono visualizzati non e' realmente importante,
       ma io ti raccomando di mostrare per ultima la finestra cosi' che tutto 
       sia visualizzato in una volta sola */
    gtk_widget_show(button);

    gtk_widget_show(box1);

    gtk_widget_show (window);

    /* e ora ci mettiamo in gtk_main e aspettiamo che il diverimento inizi.
    gtk_main ();

    return 0;
}

Compilate questo programma usando gli stessi argomenti di link del nostro primo esempio. Noterete che questa volta non c'è un modo semplice per uscire dal programma, si deve usare il nostro window manager o la linea di comando per uccidere l'applicazione. Un buon esercizio per il lettore è quello di inserire un tezo bottone ``quit'' che faccia uscire dal programma. Potete anche divertirvi con le opzioni di gtk_box_pack_start() mentre leggete il prossimo capitolo. Provate a ridimensionare la finestra ed a osservare cosa succede.

Solo una piccola nota: c'è un'altra definizione di gtk_window_new() - GTK_WINDOW_DIALOG. Questa interagisce con il window manager in un modo un po' diverso, e dovrebbe essere usata per finestre temporanee.


Avanti Indietro Indice