Advanced  Services draw(), resize() und handle() Back Next Up Home


draw()


Die Methode draw() zeichnet das Fenster neu, wenn Teile davon verdeckt worden sind oder das Fenster vergößert oder verkleinert wird. Mit dem folgenden kleinen Programm kann man dieses Verhalten nachvollziehen. Dazu wird eine Unterklasse MyWindow von Fl_Window erzeugt und die draw()-Methode entsprechend überschrieben.

Der Header MyWindow.h



#ifndef _MY_WINDOW_
#define _MY_WINDOW_

#include <Fl_Window.H>
#include <stdio.h>


class MyWindow : public Fl_Window
{
public:
   MyWindow(int x, int y, int w, int h, const char* poi=0) : Fl_Window(x, y, w, h, poi)
   {
   }

   MyWindow(int w, int h, const char* poi=0) : Fl_Window(w, h, poi)
   {
   }

   MyWindow::~MyWindow()
   {}

   // draw wird überschrieben
   void draw();
};
#endif   // end _MY_WINDOW_


Die Implementierung mywindow.cpp



/*
   implementierung von MyWindow: public Fl_Window
*/

#include "MyWindow.h"

void MyWindow::draw()
{
   static int count=0;
   Fl_Window::draw();
   printf("draw called %d\n", ++count);

}


main()



/*
   das beispiel demonstriert den aufruf der draw()-methode
   dazu wird eine unterklasse MyWindow von Fl_Window erzeugt
   und die draw()-methode entsprechend überschrieben.
   auch bei eingaben in Fl_Input wird die draw()-methode gerufen.
*/

#include <Fl.H>
#include <Fl_Window.H>
#include <Fl_Widget.h>
#include <Fl_Input.H>

#include "MyWindow.h"

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

   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_Input *inputField = new Fl_Input(20, 80, 150, 30);
   inputField->value(" enter text");

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

Und so sieht das aus:

DrawDemo.jpg


resize()


Die Methode resize() wird natürlich immer dann gerufen wenn sich die Fenstergröße ändert. Sie wird aber auch gerufen wenn man das Fenster lediglich verschiebt.

Der Header MyWindow.h



#ifndef _MY_WINDOW_
#define _MY_WINDOW_

#include <Fl_Window.H>
#include <stdio.h>


class MyWindow : public Fl_Window
{
public:
   MyWindow(int x, int y, int w, int h, const char* poi=0) : Fl_Window(x, y, w, h, poi)
   {
   }

   MyWindow(int w, int h, const char* poi=0) : Fl_Window(w, h, poi)
   {
   }

   MyWindow::~MyWindow()
   {}

   // resize wird überschrieben
   void resize(int x, int y, int w, int h) ;
};
#endif   // end _MY_WINDOW_

Die Implementierung mywindow.cpp



/*
   implementierung von MyWindow: public Fl_Window
*/

#include "MyWindow.h"

void MyWindow::resize(int x, int y, int w, int h)
{
   static int count=0;
   Fl_Window::resize(x, y, w, h);
   printf("resize called %d\n", ++count);

}

main()



/*
   wie und wann wird resize aufgerufen
   dazu
   unterklasse von Fl_Window erstellen

   und darin die resize-methode überschreiben

   void resize(int x, int y, int w, int h)
   {
      Fl_Window::resize(x, y, w, h);
      printf("resize called\n");
   }

   wie man natürlich vermuten kann, wird resize bei größenänderungen gerufen
   es wird aber auch bei reinen move-vorgängen gerufen.
*/

#include <Fl.H>
#include <Fl_Window.H>

#include "MyWindow.h"

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

   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);

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

Und so sieht das aus:

ResizeDemo.jpg


handle() zum Ersten


Die zweifelslos interessanteste Methode ist die handle()-Methode. Hier landen nämlich alle Events. Über den übergebenen int-Wert lassen sich die Events identifizieren. Im ersten Beipiel überschreiben wir die handle()-Methode und lassen uns nur die Eventnummer ausgeben. Man erkennt Mouseevents, Focusevents und Keyboardevents.

Der Header MyWindow.h



#ifndef _MY_WINDOW_
#define _MY_WINDOW_

#include <Fl_Window.H>
#include <stdio.h>

class MyWindow : public Fl_Window
{
public:
   MyWindow(int x, int y, int w, int h, const char* poi=0) : Fl_Window(x, y, w, h, poi)
   {
   }

   MyWindow(int w, int h, const char* poi=0) : Fl_Window(w, h, poi)
   {
   }

   MyWindow::~MyWindow()
   {}

   // handle wird überschrieben
   int handle(int e);
};
#endif   // end _MY_WINDOW_

Die Implementierung mywindow.cpp



/*
   implementierung von MyWindow: public Fl_Window
*/

#include "MyWindow.h"

int MyWindow::handle(int e)
{
   static int count=0;
   printf("event number %d\n", e);

   return Fl_Window::handle(e);
}

main()



/*
   wie und wann wird handle aufgerufen
   dazu
   unterklasse von Fl_Window erstellen

   und darin die handle-methode überschreiben
*/

#include <Fl.H>
#include <Fl_Window.H>

#include "MyWindow.h"

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

   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);

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

Und so sieht das aus:

HandleDemo1.jpg


handle() zum Zweiten


In diesem Beispiel werden wir die Events genau zuordnen. Anhand der Nummern sind die Events zu unterscheiden. Man sollte allerdings nie die Zahlen direkt verwenden (keine magic numbers im Programm !) sondern immer die über define festgelegten Bezeichner. Diese sind in Enumerations.H vereinbart.

Bei Mouseevents erfährt man über die Klassenmethode Fl::event_button() welcher Mousebutton gedrückt wurde. Die Klassenmethoden Fl::event_x() und Fl::event_y() liefern dann die Koordinaten.

Bei Keyevents liefert int key = Fl::event_key(); die Tastennummer und const char* text = Fl::event_text(); den Buchstaben der gedrückten Taste. Vorsicht, die letzte Methode gibt einen klassischen c-String zurück!

Der Header MyWindow.h



#ifndef _MY_WINDOW_
#define _MY_WINDOW_

#include <Fl.H>
#include <Fl_Window.H>
#include <stdio.h>

class MyWindow : public Fl_Window
{
public:
   MyWindow(int x, int y, int w, int h, const char* poi=0) : Fl_Window(x, y, w, h, poi)
   {
   }

   MyWindow(int w, int h, const char* poi=0) : Fl_Window(w, h, poi)
   {
   }

   MyWindow::~MyWindow()
   {}

   // handle wird überschrieben
   int handle(int e);
};
#endif   // end _MY_WINDOW_

Die Implementierung mywindow.cpp



/*
   implementierung von MyWindow: public Fl_Window

   behandeln von

   mouseevents
   focusevents
   keyevents

   das geht natürlich genauso für alle anderen widgets

   FL_PUSH etc. sind globale konstanten

   das ist alles vereinbart in

   Enumerations.H

   enum Fl_Event
   {  // events
     FL_NO_EVENT     = 0,
     FL_PUSH      = 1,
     FL_RELEASE      = 2,
     FL_ENTER     = 3,
     FL_LEAVE     = 4,
     FL_DRAG      = 5,
     FL_FOCUS     = 6,
     FL_UNFOCUS      = 7,
     FL_KEYDOWN      = 8,
     FL_KEYUP     = 9,
     FL_CLOSE     = 10,
     FL_MOVE      = 11,
     FL_SHORTCUT     = 12,
     FL_DEACTIVATE      = 13,
     FL_ACTIVATE     = 14,
     FL_HIDE      = 15,
     FL_SHOW      = 16,
     FL_PASTE     = 17,
     FL_SELECTIONCLEAR  = 18,
     FL_MOUSEWHEEL      = 19,
     FL_DND_ENTER    = 20,
     FL_DND_DRAG     = 21,
     FL_DND_LEAVE    = 22,
     FL_DND_RELEASE  = 23
   };


   // Fl::event_button():
   #define FL_LEFT_MOUSE   1
   #define FL_MIDDLE_MOUSE 2
   #define FL_RIGHT_MOUSE  3
*/

#include "MyWindow.h"

int MyWindow::handle(int e)
{
   static int count=0;
   printf("event number %d\n", e);

   switch(e)
   {
      // mouse events
      case FL_PUSH:     {
                           int mouseButton = Fl::event_button();
                           printf("FL_PUSH event number %d\n", e);      // 1
                           printf("mouseButton = %d\n",mouseButton); // 1 = links, 3 = rechts
                           int x = Fl::event_x() ;
                           int y = Fl::event_y();
                           printf("x = %d\n", x);  // koordinaten
                           printf("y = %d\n", y);  // koordinaten
                           break;
                        }
      case FL_RELEASE:     printf("FL_RELEASE event number %d\n", e);   // 2
                           break;
      case FL_DRAG:        printf("FL_DRAG event number %d\n", e);      // 5
                           break;
      case FL_MOVE:        printf("FL_MOVE event number %d\n", e);      // 11
                           break;
      case FL_MOUSEWHEEL:  printf("FL_MOUSEWHEEL event number %d\n", e); // 19
                           break;

      // focus events
      case FL_FOCUS:       printf("FL_FOCUS event number %d\n", e);  // 6
                           break;
      case FL_UNFOCUS:     printf("FL_UNFOCUS event number %d\n", e);  // 7
                           break;
      case FL_ENTER:       printf("FL_ENTER event number %d\n", e);
                           break;
      case FL_LEAVE:       printf("FL_LEAVE event number %d\n", e);  // 4
                           break;

      // key events
      case FL_KEYDOWN:  {
                           printf("FL_KEYDOWN event number %d\n", e);   // 8
                           int key = Fl::event_key();
                           const char* text = Fl::event_text();
                           printf("key = %d\n", key); //
                           printf("text = %s\n", text);  //
                           break;
                        }
      case FL_KEYUP:       printf("FL_KEYUP event number %d\n", e);  // 9
                           break;
      case FL_SHORTCUT:    printf("FL_SHORTCUT event number %d\n", e);  // 12
                           break;
   }
   return Fl_Window::handle(e);
}

main()



/*
   wie und wann wird handle aufgerufen
   dazu
   unterklasse von Fl_Window erstellen

   und darin die handle-methode überschreiben
*/

#include <Fl.H>
#include <Fl_Window.H>

#include "MyWindow.h"

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

   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);

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

Und so sieht das aus:

HandleDemo2.jpg


handle() zum Dritten


In diesem Beispiel werden wir die Behandlung der Events verlagern. Statt in handle() selbst zu reagieren, leiten wir die Events in die callback()-Methode weiter und reagieren dann in dieser Methode.

Der Header MyWindow.h



#ifndef _MY_WINDOW_
#define _MY_WINDOW_

#include <Fl_Window.H>

class MyWindow : public Fl_Window
{
public:
   MyWindow(int x, int y, int w, int h, const char* poi=0) : Fl_Window(x, y, w, h, poi)
   {
   }

   MyWindow(int w, int h, const char* poi=0) : Fl_Window(w, h, poi)
   {
   }

   MyWindow::~MyWindow()
   {}

   // handle wird überschrieben
   int handle(int e);
};
#endif   // end _MY_WINDOW_

Die Implementierung mywindow.cpp



/*
   implementierung von MyWindow: public Fl_Window
   weiterleiten der events an die callbackfunktion
*/

#include "MyWindow.h"

int MyWindow::handle(int e)
{
   // weiterleitung an die callback()-funktion
   this->do_callback(this, e);

   return Fl_Window::handle(e);
}

main()



/*
   wie und wann wird handle aufgerufen
   dazu
   unterklasse von Fl_Window erstellen

   und darin die handle-methode überschreiben
   events weiterleiten an die callback-funktion
*/

#include <Fl.H>
#include <Fl_Window.H>
#include <stdio.h>

#include "MyWindow.h"

void eventHandler(Fl_Widget* source, long ev);

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

   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);

   win.callback(eventHandler);

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


void eventHandler(Fl_Widget* source, long e)
{
   //printf("event number %d\n", e);

   switch(e)
   {
      // mouse events
      case FL_PUSH:     {
                           int mouseButton = Fl::event_button();
                           printf("FL_PUSH event number %d\n", e);      // 1
                           printf("mouseButton = %d\n",mouseButton); // 1 = links, 3 = rechts
                           int x = Fl::event_x() ;
                           int y = Fl::event_y();
                           printf("x = %d\n", x);  // koordinaten
                           printf("y = %d\n", y);  // koordinaten
                           break;
                        }
      case FL_RELEASE:     printf("FL_RELEASE event number %d\n", e);   // 2
                           break;
      case FL_DRAG:        printf("FL_DRAG event number %d\n", e);      // 5
                           break;
      case FL_MOVE:        printf("FL_MOVE event number %d\n", e);      // 11
                           break;
      case FL_MOUSEWHEEL:  printf("FL_MOUSEWHEEL event number %d\n", e); // 19
                           break;

      // focus events
      case FL_FOCUS:       printf("FL_FOCUS event number %d\n", e);  // 6
                           break;
      case FL_UNFOCUS:     printf("FL_UNFOCUS event number %d\n", e);  // 7
                           break;
      case FL_ENTER:       printf("FL_ENTER event number %d\n", e);
                           break;
      case FL_LEAVE:       printf("FL_LEAVE event number %d\n", e);  // 4
                           break;

      // key events
      case FL_KEYDOWN:  {
                           printf("FL_KEYDOWN event number %d\n", e);   // 8
                           int key = Fl::event_key();
                           const char* text = Fl::event_text();
                           printf("key = %d\n", key); //
                           printf("text = %s\n", text);  //
                           break;
                        }
      case FL_KEYUP:       printf("FL_KEYUP event number %d\n", e);  // 9
                           break;
      case FL_SHORTCUT:    printf("FL_SHORTCUT event number %d\n", e);  // 12
                           break;
   }

}

Kleine Anwendung unserer Erkenntnisse


Wir schreiben eine kleine Anwendung, bei der sich eine Komponente automatisch an die größe des Hauptfensters anpaßt. Dabei kann man sehen wie man von einem Hauptfenster auf die Komponenten zugreift und auch umgekehrt, wie man über eine Kindkomponente die Elternkomponente erhält.

Erste Variante: Reaktion in der resize()-Methode


Der Header MyWindow.h



#ifndef _MY_WINDOW_
#define _MY_WINDOW_

#include <Fl_Window.H>
#include <Fl_Widget.H>


class MyWindow : public Fl_Window
{
public:
   MyWindow(int x, int y, int w, int h, const char* poi=0) : Fl_Window(x, y, w, h, poi)
   {
   }

   MyWindow(int w, int h, const char* poi=0) : Fl_Window(w, h, poi)
   {
   }

   MyWindow::~MyWindow()
   {}

   // resize wird überschrieben
   void resize(int x, int y, int w, int h) ;
};
#endif   // end _MY_WINDOW_

Die Implementierung mywindow.cpp



/*
   implementierung von MyWindow: public Fl_Window
   das hauptfenster ermittelt die (einzige) child-komponente
   und paßt die größe an
*/

#include "MyWindow.h"

void MyWindow::resize(int x, int y, int w, int h)
{
   Fl_Window::resize(x, y, w, h);

   // dieses child ist der button !
   Fl_Widget* child = this->child(0);
   child->resize(child->x(), child->y(), this->w(), child->h() ) ;
}

main()



/*
   hier muß nur noch das fenster und der button angelegt werden
*/

#include <Fl.H>
#include <Fl_Window.H>
#include <stdio.h>

#include "MyWindow.h"

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

   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(0, 0, 350, 30, "drück mich");

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

Zweite Variante: Weiterleitung mit do_callback() und Reaktion in der callback()-Methode


Der Header MyWindow.h



#ifndef _MY_WINDOW_
#define _MY_WINDOW_

#include <Fl_Window.H>
#include <Fl_Widget.H>


class MyWindow : public Fl_Window
{
public:
   MyWindow(int x, int y, int w, int h, const char* poi=0) : Fl_Window(x, y, w, h, poi)
   {
   }

   MyWindow(int w, int h, const char* poi=0) : Fl_Window(w, h, poi)
   {
   }

   MyWindow::~MyWindow()
   {}

   // resize wird überschrieben
   void resize(int x, int y, int w, int h) ;
};
#endif   // end _MY_WINDOW_

Die Implementierung mywindow.cpp



/*
   implementierung von MyWindow: public Fl_Window
   das hauptfenster ermittelt die (einzige) child-komponente
   und paßt die größe an
*/

#include "MyWindow.h"

void MyWindow::resize(int x, int y, int w, int h)
{
   Fl_Window::resize(x, y, w, h);

   // weiterleiten
   this->do_callback();
}

main()



/*
   hier muß jetzt die größenanpassung in der callback()-methode stattfinden
*/

#include <Fl.H>
#include <Fl_Window.H>
#include <stdio.h>

#include "MyWindow.h"


void winAction(Fl_Widget* o, void* b);


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

   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(0, 0, 350, 30, "drück mich");
   // die methode callback wird zu win gerufen, ein pointer auf den button wird übergeben
   win.callback(winAction, button);

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


void winAction(Fl_Widget* o, void* b)
{
   int e = Fl::event() ;
   //printf("winaction event = %d\n", e);

   // b ist ein pointer auf den button
   Fl_Button *butt = (Fl_Button*)b;
   // so bekommt man die parentkonponente
   Fl_Window *win = butt->window();
   // buttongröße anpassen
   butt->resize(butt->x(), butt->y(), win->w(), butt->h() ) ;

   // beendet die anwendung
   if( e == FL_CLOSE)
      exit(0);
}

Und so sieht das aus:

ResizeButton1.jpg   ResizeButton2.jpg

top Back Next Up Home