Gestion des événements liés à la fenêtre et aux périphériques dentrée.

25
Gestion des événements liés à la fenêtre et aux périphériques d’entrée

Transcript of Gestion des événements liés à la fenêtre et aux périphériques dentrée.

Page 1: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

Gestion des événementsliés

à la fenêtreet

aux périphériques d’entrée

Page 2: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

2

Programmation par événement L’usager peut déplacer ou changer la dimension d’une fenêtre à l’écran

au moyen de la souris, changer le repère de la caméra, modifier lescaractéristiques géométriques des objets de la scène, etc.

Habituellement, on opte pour un mode de gestion par événement des périphériquesd’entrée :

- À chaque fois qu’un signal est transmis d’un périphérique d’entrée (pression d’un bouton ou d’une clé), un nouvel événement est créé.

- La donnée obtenue et un identificateur du périphérique d’entrée sont rangés dans une file d’événements.

-  Les événements sont traités selon un protocole « premier arrivé - premier servi ».

-  À chaque type d’événement est associé une fonction de prise en compte de cet événement permettant de gérer les actions à prendre selon l’état d’un périphérique.

Le traitement d’un événement dans la file consiste donc à exécuter cette fonction de prise en compte de ce type d’événement.

Page 3: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

3

Gestion des événements en OpenGL OpenGL fournit différents outils pour faciliter la gestion des événements :

glutMouseFunc(Souris);

où « Souris » est la fonction de prise en compte d’un événement associé à lasouris.

glutKeyboardFunc(Clavier);

où « Clavier » est la fonction de prise en compte d’un événement associé auclavier.

Exemple : Lorsque vous pressez ou relâchez un bouton de la souris,pressez une touche du clavier, ou déplacez la souris,un nouvel événement est créé.

Page 4: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

4

Gestion du clavierEn pressant une touche sur le clavier, un événement est généré qui doit être pris encompte :

glutKeyboardFunc(Clavier);

L’entête de la fonction « Clavier » est comme suit :

void Clavier(unsigned char cle, int x, int y);

La valeur de « cle » correspond à la valeur ASCII de la touche sélectionnée.

x et y désignent la position de la souris lorsque la touche a été pressée.

Plusieurs clés peuvent être utilisées dans une application offrant un grand éventailde choix à l’usager.

Page 5: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

5

Usage de clés spécialesLes touches spéciales F1, F2, …. et les flèches peuvent être utilisées grâce à laprimitive glutSpecialFunc ().

En pressant une telle touche sur le clavier, un événement est généré qui doit êtrepris en compte :

glutSpecialFunc(Touches_speciales);

L’entête de la fonction « Clavier » est comme suit :

void Touches_speciales(int cle, int x, int y);

À l’intérieur de cette fonction, on pourrait par ex. effectuer les tests suivants :

if (cle == GLUT_KEY_F1) . . . ou encore

if (cle == GLUT_KEY_UP) . . .

Page 6: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

6

Usage de clés spécialesLes touches spéciales Ctrl, Alt et Shift peuvent être utilisées grâce à laprimitive glutGetModifiers().

int glutGetModifiers();

Retourne l’une des valeurs suivantes : GLUT_ACTIVE_SHIFT, GLUT_ACTIVE_CTRL, GLUT_ACTIVE_ALT,

si cette touche est pressée au moment où un événement provenant du clavier oude la souris est généré.

Exemple : Arrêt d’un programme lors de la prise en compte d’un événementprovenant du clavier.

if ((glutGetModifiers() == GLUT_ACTIVE_CTRL) && ((cle == 'c' || (cle == 'C'))) exit(0);

Page 7: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

7

Gestion de la sourisPour spécifier le nom de la fonction (en l’occurrence, la fonction « Souris ») quiprendra en compte l’événement qui intervient lorsqu’un bouton de la souris est presséou relâché, on a l’instruction d’OpenGL suivante :

glutMouseFunc(Souris);

L’entête de cette fonction a la forme suivante :

void Souris(int bouton, int etat, int x, int y);

où « bouton » peut prendre l’une des valeurs suivantes :

GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON etGLUT_RIGHT_BUTTON,

« etat » peut prendre l’une des 2 valeurs GLUT_UP ou GLUT_DOWN,

« x, y » désigne la position de la souris lorsque l’événement survient.Note : « x » désigne le # de pixels à partir de la gauche de la fenêtre,

« y » désigne le # de pixels à partir du haut de la fenêtre.

Page 8: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

8

Exemple I :

Lorsque l’usager presse le bouton gauche de la souris, un point sera affiché à lafenêtre de l’écran à la position de la souris.

Lorsqu’il presse le bouton droit, le programme termine.

void Souris(int bouton, int etat, int x, int y){

if((bouton == GLUT_LEFT_BUTTON) && (etat == GLUT_DOWN)){

glBegin(GL_POINTS);glVertex2i(x, H – y);

glEnd();}else if ((bouton == GLUT_RIGHT_BUTTON) &&

(etat == GLUT_DOWN)) exit(-1);}Note : H désigne la hauteur de la fenêtre en pixels.

Page 9: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

9

Exemple II :

Permet de tracer un rectangle à l’aide de la souris en pointant 2 sommets opposés de lafigure.

Chaque nouveau rectangle remplace le précédent; par conséquent, uniquement les 2sommets du rectangle courant sont conservés. Lorsque les 2 sommets sont spécifiés,le rectangle est tracé.

On peut aussi effacer l’écran en pressant le bouton droit de la souris.

void Souris(int bouton, int etat, int x, int y){

/* « static » permet de conserver les valeurs des variables d’un appel de la fonction à un autre. */static GLint sommet_x[2];static GLint sommet_y[2];static int Nombre_de_sommets = 0;

Page 10: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

10

if((bouton == GLUT_LEFT_BUTTON) &&(etat == GLUT_DOWN))

{sommet_x[Nombre_de_sommets] = x;sommet_y[Nombre_de_sommets] = H – y;Nombre_de_sommets ++;if(Nombre_de_sommets == 2){

glRecti(sommet_x[0], sommet_y[0],sommet_x[1], sommet_y[1]);

Nombre_de_sommets = 0;}

}else if ((bouton == GLUT_RIGHT_BUTTON) &&

(etat == GLUT_DOWN))glClear(GL_COLOR_BUFFER_BIT);

glFlush();}

Page 11: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

11

Exemple III :Nous allons tracer un « polyline » de manière interactive.

La liste de sommets est spécifiée à l’aide de la souris;

chaque nouveau sommet est rangé à la suite des autres.

Si le nombre maximum de sommets est atteint, aucun nouveau sommet sera accepté.

Lorsque le bouton de gauche est pressé, le dernier segment est tracé.

Lorsque le bouton de droite est pressé, la fenêtre est effacée et tous les sommets sontdétruits.

Page 12: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

12

void Souris(int bouton, int etat, int x, int y){

#define MAX 20typedef GLint point_2D[2];static point_2D liste[MAX]; static int dernier = -1;if((bouton == GLUT_LEFT_BUTTON) &&

(etat == GLUT_DOWN)) && (dernier < (MAX – 1))){

liste[++dernier][0] = x; liste[dernier][1] = H – y;if(dernier > 0){ glBegin(GL_LINES);

glVertex2i(liste[dernier-1][0], liste[dernier-1][1]);glVertex2i(liste[dernier][0], liste[dernier][1]);

glEnd();glFlush();

}}else if ((bouton == GLUT_RIGHT_BUTTON) && (etat == GLUT_DOWN)){

dernier = -1; glClear(GL_COLOR_BUFFER_BIT); glFlush();}

}

Page 13: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

13

Exemple IV : Tracé d’une courbe ou d’un polyline.

static GLint dernier = -1;static GLint Liste[50][2];void Initialisation(void){

glClearColor(0.0, 0.0, 0.0, 0.0);glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glMatrixMode(GL_PROJECTION); glLoadIdentity();gluOrtho2D(0.0, 800.0, 0.0, 500.0);

}void Affichage(){ glFlush();}void reconfiguration(int w, int h){

glViewport(0, 0, (GLsizei) w, (GLsizei) h);glMatrixMode(GL_PROJECTION); glLoadIdentity();gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);

}

Page 14: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

14

En conservant la clé ‘t’enfoncée tout en déplaçantla souris, cela revient àeffectuer un tracé à la main.

void Clavier(unsigned char cle, int sx, int sy){ int i;

glColor3f(1.0, 0.0, 0.0);GLint x = sx; GLint y = 500 - sy;switch(cle){ case 't' : // Tracé d’un point.

glBegin(GL_POINTS);glVertex2i(x, y);

glEnd();break;

case 'p' : // Tracé d'un polyline.glBegin(GL_LINE_STRIP);

for (i = 0; i <= dernier; i++)glVertex2i(Liste[i][0], Liste[i][1]);

glEnd();break;

case 'E' : exit(-1); // Permet de terminer le programme.default : break; // Aucune action.

};glFlush();

}

Page 15: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

15

void Ajouter_Position(int cle, int sx, int sy){ // La clé «  » permet d’ajouter une position à une liste.

if (cle == GLUT_KEY_LEFT){ Liste[++dernier][0] = sx; Liste[dernier][1] = 500 - sy;} else exit(-1);

}void main(int argc, char** argv){ glutInit(&argc, argv);

glutInitDisplayMode (GLUT_RGB);glutInitWindowSize(800, 500);glutInitWindowPosition(500, 100);glutCreateWindow("Trace de courbe ou polyline");

glutDisplayFunc(Affichage);glutKeyboardFunc(Clavier);glutSpecialFunc(Ajouter_Position);glutReshapeFunc(reconfiguration);

Initialisation();glutMainLoop();

}

Page 16: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

16

Exemple V : Affichage d’un rectangle

Dans les exemples précédents, les primitives d’affichage se retrouvaient dans lesfonctions de prise en charge des événements au lieu de la fonction « Affichage ».On peut corriger cette situation comme dans l’exemple suivant.

static GLint x1 = 0, y1 = 0, x2 = 0, y2 = 0;static bool premier = true;

void Affichage(){

glClear(GL_COLOR_BUFFER_BIT);glBegin(GL_POLYGON);

glVertex2i(x1, y1);glVertex2i(x1, y2);glVertex2i(x2, y2);glVertex2i(x2, y1);

glEnd();glFlush();

}

Page 17: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

17

void Souris(int bouton, int etat, int x, int y){

glColor3f(1.0, 0.0, 0.0);if(etat == GLUT_DOWN && bouton == GLUT_LEFT_BUTTON) exit(-1);if(etat == GLUT_DOWN && bouton == GLUT_RIGHT_BUTTON){

if (premier){

x1 = x; y1 = 500 - y;premier = ! premier;

}else{

premier = ! premier;x2 = x; y2 = 500 - y;glutPostRedisplay(); // Rappeler la fonction Affichage.

}}glFlush();

}

Page 18: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

18

Mouvement de la sourisDes événements sont aussi générés lorsque vous déplacez la souris.

1er cas : la souris est déplacée en même temps que vous pressez sur un bouton.

void glutMotionFunc(void(*f) (int x, int y));

La fonction f permet de prendre en compte cet événementoù (x, y) désigne la position de la souris.

2ième cas : la souris est déplacée sans que vous pressiez sur un bouton.

void glutPassiveMotionFunc(void(*f) (int x, int y));

La fonction f permet de prendre en compte cet événementoù (x, y) désigne la position de la souris.

Page 19: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

19

Exemple VI : Affichage d’une courbe en déplaçant la souris le longd’une trajectoire tout en conservant un bouton pressé.

GLint Largeur_brosse = 20;void Souris_en_mouvement(int sx, int sy){

glRecti(sx, 500 - sy, sx + Largeur_brosse, 500 - sy + Largeur_brosse);glFlush();

}void Affichage(){

glClear(GL_COLOR_BUFFER_BIT);glFlush();

}void main(int argc, char** argv){

. . . glutDisplayFunc(Affichage);glutMotionFunc(Souris_en_mouvement);glutReshapeFunc(reconfiguration);. . .

}

Page 20: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

20

Gestion des menusGLUT permet de créer et de gérer des menus. Ces menus apparaissent lorsqu’onpresse un bouton de la souris.

4 étapes :

1. Identification d’une fonction qui prendra en compte chaque élément du menu.

int glutCreateMenu(void (*f) (int v));

La fonction f pose les gestes voulus pour chaque valeur de v.Le menu créé devient le menu courant.

2. Ajout d’une entrée au menu courant.

void glutAddMenuEntry(char * nom, int v);

Ajoute une entrée au menu identifiée par une chaîne de caractères.v désigne le numéro de cette entrée.

3. Établir le lien entre ce menu et un bouton de la souris(GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON ou GLUT_LEFT_BUTTON).

void glutAttachMenu(int bouton);

Page 21: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

21

4. Implantation de la fonction qui prendra en compte chaque élément du menu.

void f(int v){

if (v == 1) . . .if (v == 2) . . .. . .

}

Note :

Le menu créé à l’étape 1 devient le menu courant mais celui-ci peut êtrechangé grâce à la fonction : void glutSetMenu(int id);

Nous pouvons ajouter des sous-menus à un menu principal :

void glutAddSubMenu(char * nom, int m);

« nom » désigne une nouvelle entrée au menu courant laquelle est unsous-menu dont le numéro « m » est la valeur entière retournée lorsquele sous-menu est créé.

Page 22: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

22

Exemple VII : Reprise de l’exemple IV où un menu principal estajouté en lien avec le bouton droit de la souris.

void Menu_principal(int valeur){

if (valeur == 1){

glBegin(GL_LINE_STRIP);for (int i = 0; i <= dernier; i++)

glVertex2i(Liste[i][0], Liste[i][1]);glEnd();

};if (valeur == 2) glClear(GL_COLOR_BUFFER_BIT);if (valeur == 3) exit(0);

glFlush();}

Page 23: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

23

void main(int argc, char** argv){

glutInit(&argc, argv);glutInitDisplayMode (GLUT_RGB);glutInitWindowSize(800, 500);glutInitWindowPosition(500, 100);glutCreateWindow("Trace de courbe ou polyline");glutDisplayFunc(Affichage);glutKeyboardFunc(Clavier);glutSpecialFunc(Ajouter_Position);

glutCreateMenu(Menu_principal);glutAddMenuEntry("Affichez le polyline.", 1);glutAddMenuEntry("Effacez l'ecran.", 2);glutAddMenuEntry("Quittez l'application.", 3);glutAttachMenu(GLUT_RIGHT_BUTTON);

glutReshapeFunc(reconfiguration);Initialisation();glutMainLoop();

}

Page 24: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

24

Gérer un processus à l’arrière-planVous pouvez spécifier une fonction qui devra s’exécuter si aucun autre événementn’est en cours :

void glutIdleFunc(void (*f)(void));

Pour désactiver l’exécution de la fonction, on peut utiliser la primitive précédenteen passant en paramètre la valeur NULL.

Cela est particulièrement intéressant en animation.

Page 25: Gestion des événements liés à la fenêtre et aux périphériques dentrée.

25

Gestion des événements liés aux fenêtres

Spécifier la fonction appelée lorsque le contenu de la fenêtre doit être redessiné :

void glutDisplayFunc(void (*f)(void));

Spécifier la fonction appelée lorsque la fenêtre est redimensionnée ou déplacée :

void glutReshapeFunc(void (*f)(int L, int h));

Les 2 paramètres désignent la largeur et la hauteur de la fenêtre.En général, la fonction f renferme un appel à glViewport(), de manièreque l’affichage soit découpé à la nouvelle taille, et redéfinit la matricede projection pour que le ratio de l’image projetée corresponde aucadrage afin d’éviter les distorsions.

Spécifier que le contenu de la fenêtre active doit être redessiné.

void glutPostRedisplay(void);

La fonction f de glutDisplayFunc sera appelée.