Advanced  Services Eventhandling mit callback() Back Next Up Home


Vorspann



Das letzte Beispiel ist natürlich unbefriedigend. Was nützt eine Texteingabe, wenn man nicht darauf reagieren kann. Graphische Oberflächen sind ohne Eventhandling nicht denkbar. Meist beginnt man das Eventhandling mit der Reaktion auf einen Buttonclick. Erstens wird das ständig gebraucht und zweitens ist das in der Regel der einfachste Einstieg in das Thema.


Die callback()-Methode


Die callback()-Methoden werden in der Klasse Fl_Widget eingeführt und stehen damit sämtlichen Widgets zur Verfügung. Es gibt vier verschiedene Ausprägungen dieser Methode. Sie sind schöne Beispiele für den Einsatz von Funktionspointern. Wir behandeln hier nur eine dieser Methoden:


typedef void (Fl_Callback)(Fl_Widget*, void*)
void Fl_Widget::callback(Fl_Callback*, void* = 0)

Die Methode hat zwei Pointer in der Parameterliste, der erste Parameter ist ein Pointer auf eine Funktion. Damit kann das Widget diese Funktion rufen, wenn ein Ereignis eingetreten ist. Diese Funktion ist nicht an eine Klasse gebunden und hat in der Parameterliste das Widget, das die Quelle des Ereignisses ist und als zweiten Parameter einen typenloser Pointer. Falls man in der callback-Methode den zweiten Parameter einsetzt, so wird er an die aufzurufende Funktion weitergereicht. Wir weden noch sehen, daß dieses Konzept äußerst nützlich ist.


Reaktion auf einen Buttonclick, Ausgabe auf die Konsole


Das folgende Codefragment erzeugt einen Button, sowie die Reaktionsfunktion buttonAction() und zeigt zudem, wie diese callback() eingesetzt wird.


/*
   reaktion auf button
*/

#include <FL.H>
#include <Fl_Widget.h>
#include <Fl_Window.H>
#include <Fl_Button.H>
#include <stdio.h>


void buttonAction(Fl_Widget* o, void*);

int main()
{
   //x = 300, y = 400 relative zum screen
   Fl_Window win(300,300,300,200, "Hello FLTK");
   win.size_range(150,100);  // minimale größe
   // durch diese angabe wird das fenster resizable

   Fl_Color col = fl_rgb_color(200,220,240);
   //hintergrundfarbe setzen
   win.color(col);

   // x=20, y=20, width=150, height=30
   Fl_Button *button = new Fl_Button(20, 20, 150, 30, "drück mich");
   // die methode callback bekommt einen funktionspointer !
   button->callback( buttonAction );

   win.show();
   return Fl::run();
}


void buttonAction(Fl_Widget* source, void* v)
{
   static int i = 0;
   char dest[30] ;
   sprintf(dest, "button pressed %d", ++i);
   printf("%s\n", dest);
}


Und so sieht das aus:

example-03.jpg



Reaktion auf einen Buttonclick, Ausgabe im Fenster


Das folgende Codefragment erzeugt einen Button, sowie die Reaktionsfunktion buttonAction() und zeigt zudem, wie diese callback() eingesetzt wird.


/*
   reaktion auf button
*/

#include <FL.H>
#include <Fl_Widget.h>
#include <Fl_Window.H>
#include <Fl_Button.H>
#include <stdio.h>


void buttonAction(Fl_Widget* o, void*);


int main()
{
   //x = 300, y = 300 relative zum screen
   Fl_Window win(300,300,350,250, "Hello FLTK");
   win.size_range(150,100);  // minimale größe
   // durch diese angabe wird das fenster resizable

   Fl_Color col = fl_rgb_color(200,220,240);
   //hintergrundfarbe setzen
   win.color(col);

   // x=20, y=80, width=150, height=30
   Fl_Output *outputField = new Fl_Output(20, 80, 150, 30);
   outputField->value(" button unpressed");

   // x=20, y=20, width=150, height=30
   Fl_Button *button = new Fl_Button(20, 20, 150, 30, "drück mich");
   // die methode callback bekommt einen funktionspointer !
   button->callback( buttonAction, outputField );

   win.show();
   return Fl::run();
}


void buttonAction(Fl_Widget* source, void* widget)
{
   static int i = 0;
   char text[30] ;
   sprintf(text, " button pressed %d", ++i);

   Fl_Output *outputField = (Fl_Output*)widget;
   outputField->value(text);
}


Im obigen Beispiel übergeben wir der callback()-methode nicht nur den Funktionspointer, sondern als zweites Argument gleich noch einen Pointer auf das Ausgabefeld. Auf diese Weise können wir in der Funktion buttonAction bequem auf das Ausgabefeld zugreifen.

Und so sieht das aus:

example-04.jpg example-05.jpg



Fl_Window und callback()


Der x-Button zum Beenden der Anwendung ist bei Fl_Window schon mit der entsprechenden Funktion ausgestattet. Das Fenster wird geschlossen. was ist aber, wenn man noch Aufräumarbeiten machen will oder dem Benutzer noch eine Frage stellen will ? Dieses Problem löst die callback()-Funktion: Führt man eine callback()-Funktion für das Hauptfenster ein, so schließt dieses nicht mehr automatisch. Stattdessen wird die zuständige callback()-Funktion gerufen. Hier kann man dann abschließende Arbeiten erledigen.


/*
   führt man eine callback-funktion für das hauptfenster ein, so schließt dieses
   nicht mehr automatisch. stattdessen muß es über die callback-funktion
   geschlossen werden.
   vorteil:
   man kann abschließende arbeiten in der callback-funktion erledigen

*/

#include <Fl.H>
#include <Fl_Window.H>
#include <Fl_Widget.h>
#include <stdio.h>
#include <stdlib.h>  // für exit()



void winAction(Fl_Widget* w, void* p);


int main()
{
   //x = 300, y = 300 relative zum screen
   Fl_Window win(300,300,350,250, "Fl_WindowDemo");

   win.size_range(150,100);  // minimale größe
   // durch diese angabe wird das fenster resizable

   Fl_Color col = fl_rgb_color(200,220,240);
   //hintergrundfarbe setzen
   win.color(col);

   // hiermit wird die funktion winAction() zuständig für das beenden der anwendung
   win.callback( winAction );

   win.show();
   return Fl::run();
}


void winAction(Fl_Widget* w, void* p)
{
   // dateien schließen
   // datenbankverbindungen beenden
   // modalen dialog zeigen
   // und dann
   exit(0);
}

top Back Next Up Home