Les Évènements :
Nous allons parler d'une chose très perturbante, au début, quand on passe de la programmation procédurale (PP) à une programmation plus structurée comme la programmation orientée objet (POO), il s'agit des
Évènements et de leur
Gestion .
En PP on raisonne ainsi : quand il arrive cela on fait ceci sinon on fait autre chose car tout est purement séquentiel ; en POO , ce raisonnement (que j'ai voulu simpliste) peut être un piège dont il est difficile de sortir.
Nous allons à, travers un exemple, le voir . Téléchargeable ici :
Les Évènements Que doit faire notre programme :
nous voulons créer une alarme que l'utilisateur puisse régler et déclencher à travers un décompte de temps.
De quoi avons nous besoin :
- un Formulaire qui va accueillir tous les autres objets, à savoir :
- deux boutons à cliquer, un pour valider la définition des valeurs du décompte de temps rentrées par l'utilisateur, un autre pour annuler
- un Timer qui va gérer ce décompte de temps et déclencher notre alarme au bon moment
- et de quoi accueillir nos affichages de saisie genre textBox ou mieux TimeBox .
Le container principal en Gambas se nomme formulaire ou Form .
Quand on créé un Form, on génère un réceptacle pour d'autres conteneurs et objets, tout ce qui est visible et joue le rôle d'interface avec l'utilisateur.
Mais, en réalité, on a créé plus que cela ; on a modélisé une ligne d'évènements qui se nomme en Gambas,
la Boucle évènements .
Cette ligne va observer grâce à des Observer tout ce qui se passe à l'intérieur du formulaire et en fonction de la définition que le programmeur fera de ces évènements, renverra le traitement de ces évènements.
Si l'on perd cette idée de vue, nos raisonnements vont être bancales pour ne pas dire autre chose de plus définitif.
Les boutons dont on définit un évènement typique : le clique dessus, btValid_Click() ou btAnnul_Click(), l'évènement étant repérable par le _Click().
Le timer est un objet invisible (sauf dans l'IDE, en mode édition) mais bien réel qui décompte le temps et fait ce que le programmeur a décidé, ici le jeu d'un son au moment prévu par l'utilisateur.
Cet évènement est levé par le formulaire principal toutes les 1000 ms soit toutes les secondes.
Ce délai, c'est le programmeur qui le règle soit par le code soit directement dans l'IDE en modifiant la propriété Delay.
Les Procédures et fonctions restent très séquentielles dans leur approche, action après action mais les relations entre procédures se font par la levée des évènements dans la boucle évènements, et, ici plus de séquence organisée c'est bien en fonction de l'évènement levé.
Pour raisonner il faut alors penser évènement par évènement et ne pas en oublier en chemin sinon notre programme ne fera pas ce qu'on a raisonné.
Le code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| ' Gambas class file
PRIVATE iTemp AS INTEGER '<----------------------------- le décompte en seconde PRIVATE MonSon AS Sound '<--------------------------------- le son de l'alarme PRIVATE ouverture3 AS STRING = "ouverture3" '<------------- le nom du son
PUBLIC SUB son($son AS STRING) '<------------------------- définition du son
SELECT CASE $son '<------------------------------------ on peut définir plusieurs sons CASE ouverture3 '<--------------------------------- au cas où mon son est TRY MonSon = Sound.Load("ouverture3.ogg") '<- le fichier son END SELECT TRY MonSon.Play() '<--------------------------------- jeu du son
END
PUBLIC SUB timDecomp_Timer() '<------------------------- évènement de décompte du temps
DIM iHour, iMinute, iSeconde AS INTEGER '<------------- les variables locales
IF itemp > 0 THEN '<--------------------------------- si la variable est définie DEC iTemp '<------------------------------------- la variable globale est décrémentée ELSE '<--------------------------------------------- sinon on sort de l'évènement lblWillBe.Text = "" '<----------------------------- label du temps qu'il sera est vide RETURN '<----------------------------------------- retour dans la boucle évènements ENDIF
iHour = (itemp DIV 3600) MOD 3600 '<------------------- les heures à partir du temps de décompte en secondes iMinute = (itemp MOD 3600) DIV 60 '<------------------- les minutes à partir du temps de décompte en secondes ' iMinute = (itemp div 60) Mod 60 '<------------------- autre possibilité pour les minutes iSeconde = (itemp MOD 3600) MOD 60 '<----------------- les secondes à partir du temps de décompte en secondes
lblSecond.Text = CStr(iHour) & " h " & CStr(iMinute) & " m " & CStr(iSeconde) & " s " '<-- affichage repère
IF itemp = 0 THEN '<--------------------------------- nettoyage de fin de décompte son(ouverture3) '<--------------------------------- jeu du son timDecomp.Stop '<--------------------------------- arrêt de l'évènement décompte TimeBox1.Value = 0 '<----------------------------- valeur à zéro du TimeBox TimeBox1.Enabled = TRUE '<------------------------- le TimeBox est à nouveau utilisable lblSecond.Text = "" '<----------------------------- le label d'affichage du décompte est vide lblTempsRest.Visible = FALSE '<----------------- le label temps restant est vide lblWillBe.Text = "" '<----------------------------- le label du temps qu'il sera est vide btValid.Enabled = TRUE '<-------------------------- bouton valider opérationnel ENDIF
END
PUBLIC SUB btValid_Click() '<----------------------------- évènement du bouton de validation
iTemp = Hour(TimeBox1.Value) * 3600 + Minute(TimeBox1.Value) * 60 + Second(TimeBox1.Value) '<-- définition du décompte en secondes TimeBox1.Enabled = FALSE '<------------------------- le TimeBox est rendu inopérationnel lblTempsRest.Visible = TRUE '<------------------------- affichage du temps restant timDecomp.Start '<------------------------------------- déclenchement de l'évènement Timer_Décompte du temps lblWillBe.Text = Format(DateAdd(Time(Now), gb.Second, itemp), "hh:nn:ss") '<-- heure qu'il sera btValid.Enabled = FALSE '<----------------------------- bouton valider inopérationnel
END
PUBLIC SUB btAnnul_Click() '<----------------------------- évènement du bouton d'annulation
timDecomp.Stop '<------------------------------------- arrêt de l'évènement Timer_Décompte du temps et nettoyage TimeBox1.Value = 0 '<--------------------------------- le TimeBox est remis à zéro TimeBox1.Enabled = TRUE '<----------------------------- il est rendu à nouveau opérationnel lblTempsRest.Visible = FALSE '<--------------------- le label temps restant est invisible lblSecond.Text = "" '<--------------------------------- le label de décompte est vidé lblWillBe.Text = "" '<--------------------------------- le label du temps qu'il sera est vidé btValid.Enabled = TRUE '<----------------------------- bouton valider opérationnel
END
PUBLIC SUB timNow_Timer() '<----------------------------- évènement affichage de l'heure
lblNow.Text = Format(Time(Now), "hh:nn:ss") '<--------- affichage de l'heure actuelle
END
PUBLIC SUB Form_Open() '<--------------------------------- évènement ouverture du formulaire
timNow.Start '<------------------------------------- déclenchement de l'évènement Timer_Affichage de l'heure
END
|
Ce que l'IDE a écrit pour nous après que nous ayons coché des propriétés pour chaque élément utilisé, ici.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| # Gambas Form File 3.0
Form Form MoveScaled(0,0,46,31) Resizable = FALSE timDecomp #Timer #MoveScaled(0,22) } btValid Button MoveScaled(8,24,16,4) Text = ("Valider") } btAnnul Button MoveScaled(28,24,16,4) Text = ("Annuler") } Label1 Label MoveScaled(5,10,8,3) Text = ("Heures") } Label2 Label MoveScaled(18,10,8,3) Text = ("Minutes") } Label3 Label MoveScaled(31,10,13,3) Text = ("Secondes") } TimeBox1 TimeBox MoveScaled(1,14,43,4) } Label4 Label MoveScaled(1,2,24,3) Alignment = Align.Right Text = ("Il est maintenant :") } timNow #Timer #MoveScaled(39,-1) } lblNow Label MoveScaled(26,1,19,4) Font = Font["Bold,13"] } lblTempsRest Label MoveScaled(1,18,14,3) Visible = FALSE Alignment = Align.Right Text = ("Temps restant :") } lblSecond Label MoveScaled(16,18,28,3) Alignment = Align.Left } lblWillBe Label MoveScaled(26,5,19,4) Font = Font["Bold,13"] } Label5 Label MoveScaled(1,5.4286,24,3) Alignment = Align.Right Text = ("L'alarme se déclenchera à :" } }
|
Quels sont les évènements qu'observe le formulaire principal ?
À part ceux , déclarés sans avoir eu à déclarer d'observer (car le formulaire est son propre Observer) (bouton_Click, Timer_Timer), ils restent tous ceux liés au fonctionnement d'un formulaire comme l'abaissement dans la barre de tâches, l'agrandissement ou redimensionnement du formulaire, si autorisé, sans oublier, Quitter.
En conclusion, pour appréhender de façon sereine la POO, il faut raisonner évènement par évènement ; de manière autonome entre procédures, et, séquentielle dans chacune d'elles.
Le modèle objet de Gambas====================
Navigation :
<-- Liens du Wiki : <--<-- Accueil du WIKI : <-- <-- Rappels de Programmation <--====================
Documentation :
====================