Login
Newsletter
Werbung

Fr, 5. November 1999, 00:00

GTK-Workshop: Teil II

Callbacks und Signale

Eins ist klar. Irgendwie müssen nach bestimmten Ereignissen bestimmte Dinge passieren! Das ist der Sinn von Callbacks und Signalen. Callbacks werden die Funktionen genannt, die aufgerufen werden, wenn ein bestimmtes Ereignis, also ein Signal, auftritt. So macht GTK die meiste nützliche Arbeit. Für Signale gibt es zum Beispiel: "clicked", "destroy", "toggled". Dabei wird das Signal immer immer von einem Widget übergeben.

Die Funktion, die ein Signal mit einer Funktion verknüpft, ist wie folgt definiert:

gint gtk_signal_connect( GtkObject *object,
 gchar *name,
 GtkSignalFunc func,
 gpointer data );

Das erste Argument, GtkObject *object, ist das Widget, welches das Signal auslösen soll. Das zweite ist der Name des Signals (z.B. clicked), das dritte Argument ist die Funktion, die aufgerufen werden soll, wenn das Widget object das Signal name liefert. Das vierte Argument sind die Daten, die zusätzlich der Funktion übergeben werden sollen.

gtk_signal_connect( GTK_OBJECT( button ), "clicked", button_clicked, NULL ); bedeutet also, wenn button das Signal "clicked" auslöst, daß 'button_clicked' mit dem Parameter NULL (also nix) aufgerufen wird.

Der Header einer Callback-Funktion sieht meist wie folgt aus:

void callback_funktion( GtkWidget *widget,
 gpointer data );

Das erste Argument wird automatisch übergeben und ist ein Zeiger auf das Widget, welches das Signal ausgelöst hat, und das zweite Argument ist ein Zeiger auf die Parameter, die zusätzlich angegeben wurden (oben wäre es NULL). Die Callback-Funktionen müssen jedoch nicht unbedingt so aussehen.

Man kann eine Signal-zu-Funktion-Verknüpfung auch anders machen:

gint gtk_signal_connect_object(
 GtkObject *object,
 gchar *name,
 GtkSignalFunc func,
 GtkObject *object2 );

Ist eigentlich das selbe wie gtk_signal_connect(). Es gibt jedoch einen kleinen Unterschied. Die Funktion, die hier aufgerufen wird, lässt nur ein Argument zu. Hier wird object2 als erstes Argument übergeben, nicht wie oben data als zweites.

Eine Callback-Funktion kann auch an folgende X-Events gehängt werden:

  • event
  • button_press_event
  • button_release_event
  • motion_notify_event
  • delete_event
  • destroy_event
  • expose_event
  • key_press_event
  • key_release_event
  • enter_notify_event
  • leave_notify_event
  • configure_event
  • focus_in_event
  • focus_out_event
  • map_event
  • unmap_event
  • property_notify_event
  • selection_clear_event
  • selection_request_event
  • selection_notify_event
  • proximity_in_event
  • proximity_out_event
  • drag_begin_event
  • drag_end_event
  • drop_enter_event
  • drop_leave_event
  • drop_data_available_event
  • other_event

Um eine Callback-Funktion an eines dieser Signale zu hängen, einfach gtk_signal_connect() wie oben beschrieben benutzen. Der Header der Callback-Funktion muss allerdings etwas anders aussehen:

void callback_funktion( GtkWidget *widget,
 GdkEvent *event,
 gpointer data );

Wir können also z.B. ein Widget haben, das button heißt. Und wenn der Mauszeiger darüber ist und ein Mausbutton gedrückt wird, wird die Funktion mousebutton_pressed() aufgerufen:

 gtk_signal_connect( GTK_OBJECT( button ),
 "button_press_event",
 GTK_SIGNAL_FUNC(button_press_callback),
 NULL );

Dabei muss button keinesfalls ein Button sein, es könnte genauso ein Bild, ein Fenster oder ein Label (Textfeld), sein!

So und nun ein Beispiel:

/* start callbacks.c */
#include <gtk/gtk.h>
/* Eine Callback-Funktion, die aufgerufen werden soll,
 wenn die Applikation gekillt werden soll.
 Somit ist das Programm endlich beendbar */
void quit_function( GtkWidget *widget, gpointer data )
{
 g_print( "Und tschüss!" );
 gtk_main_quit();
}
/* Diese zweite Callback-Funktion wird aufgerufen,
 wenn die Applikation ordnungsgemäß beendet werden soll.
 Wenn diese Funktion FALSE zurück gibt, wird das Fenster
 gekillt. Wenn es TRUE zurück gibt, wird nicht gekillt.
 Das ist hilfreich, wenn "Sind sie sicher?" Fenster
 erscheinen sollen */
gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
{
 g_print("Fenster soll beendet werden");
 return TRUE;
}
int main( int argc, char *argv[] )
{
 /* Für die Widgets werden Variablen deklariert */
 GtkWidget *window;
 GtkWidget *button;
 /* GTK wird initialisiert */
 gtk_init( &argc, &argv );
 /* neues Fenster wird erstellt */
 window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
 /* Wenn window ein "delete_event" liefert,
    wird die Funktion delete_event() mit Parameter NULL
    aufgerufen. Ein "delete_event" wird vom Windowmanager durch
    Click auf den Schließen-Button ausgelöst /*
 gtk_signal_connect( GTK_OBJECT( window), "delete_event", GTK_SIGNAL_FUNC( delete_event ), NULL );
 /* Hier verknüpfen wir das "destroy" Signal mit einer Funktion.
    "destroy" wird durch gtk_widget_destroy() ausgelöst,
    aber auch wenn unser delete_event() FALSE zurückliefert.
    xkill hat den gleichen Effekt
    */
 gtk_signal_connect( GTK_OBJECT( window), "destroy", GTK_SIGNAL_FUNC( quit_function ), NULL );
 /* dem Aussehen wegen setzen wir den Rahmen um die Widgets auf 10 Pixel */
 gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
 /* Jetzt wird ein Knopf mit Aufschrift "Beenden" gemacht */
 button = gtk_widget_new_with_label("Beenden");
 /* Wenn der Knopf gedrückt wird, wird auch unsere Anwendung gekillt */
 gtk_signal_connect( GTK_OBJECT( button), "clicked", GTK_SIGNAL_FUNC( quit_function ), NULL );
 /* Jetzt wird der Button in das Fenster (window) getan.
    Fenster und auch andere Widgets können andere Widgets
    enthalten. Sie sind Container */
 gtk_container_add( GTK_CONTAINER( window), button );
 /* window und button sind fertig, sie können angezeigt werden */
 gtk_widget_show( button );
 gtk_widget_show( window );
 /* folgendes ist bekannt */
 gtk_main();
 return 0;
}
/* Ende callbacks.c */

Jetzt noch compilieren:

gcc -Wall -g callbacks.c -o callbacks `pkg-config --cflags gtk+-2.0 --libs`

Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung