GB3- Les évènements en Gambas( Temps de lecture estimé à 6 min 13 sec )
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 .
- 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 :
' 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
# 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.