# Reageren op gebeurtenissen, timers en berichten [Programmeergidsen](LEESMIJ.md) Een **gebeurtenis** vertelt je programma dat er iets is gebeurd, bijvoorbeeld dat een toets is ingedrukt. Een **handler**, of **gebeurtenisscript**, is het ingesprongen blok dat daarop reageert. De **kop** is de eerste regel, zoals `wanneer gestart():`. Het deel na `wanneer` heet de **gebeurtenisbeschrijving**: het vertelt waarop je reageert. Het hoort in die kop, niet in een gewone functieaanroep. **Programmaniveau** betekent buiten functies, lussen en andere blokken. Pliro voert eerst de gewone opdrachten op programmaniveau uit om het programma voor te bereiden. Dat heet **initialisatie**. Daarna krijgen de gebeurtenisscripts hun beurt. Klaarstaande scripts wachten in een **wachtrij**, zoals mensen in een rij. **Coöperatief** betekent dat een script op afgesproken punten een ander klaarstaand script aan de beurt laat, bijvoorbeeld bij een positieve `wacht`. Zie het [voorbeeld van de gebeurtenislus](../begrippen/gebeurtenissen-inplannen.md). ## Woorden over timers en beurten Een **literal** is een waarde die direct in de code staat, zoals `1` of `"start"`. Als een gebeurteniskop een literal vereist, mag daar geen variabele voor in de plaats staan. **Hoofdlettergevoelig** betekent dat `"start"` en `"Start"` verschillende berichten zijn. Een timer **activeren** betekent zijn wachttijd laten beginnen. Een **eenmalige** timer wordt één keer klaar; hij herhaalt niet. Een **deadline** is het vroegste tijdstip waarop hij mag draaien. Alle `na`-timers meten vanaf hetzelfde moment na de initialisatie. Hun **monotone klok** meet verstreken tijd zonder te springen als de tijdinstelling van de computer verandert. Gelijke deadlines houden de volgorde uit het bronbestand aan. Klaar worden onderbreekt een ander script niet midden in een opdracht. Een **aanroep** is één uitvoering van een handler. Die krijgt verse **lokale variabelen**: eigen namen binnen het blok. **Globale variabelen**, gemaakt op programmaniveau, worden gedeeld. **Afleveren**, in het Engels *dispatch*, betekent een gebeurtenis bezorgen en het passende werk klaarzetten. **Een beurt afstaan**, of *yield*, laat ander werk aan de beurt. Een **blijvende handler** houdt een geschikt draaiend programma gereed voor volgende toets- of aanwijzerinvoer, ook als het even niets doet. **Annuleren** voorkomt dat wachtend werk nog wordt uitgevoerd. ## Gebeurteniskoppen Gebeurtenisscripts staan op programmaniveau. Alleen deze directe aanroepen zijn toegestaan als gebeurtenisbeschrijving: | Kop | Betekenis | |---|---| | `wanneer gestart():` | Eén uitvoering na gewone initialisatie. | | `wanneer na(1):` | Eén uitvoering na een vaste vertraging. | | `wanneer berichtOntvangen("start"):` | Uitvoering bij een exact overeenkomend bericht. | | `wanneer toetsGedrukt("space"):` | Uitvoering bij de overgang van los naar ingedrukt. | | `wanneer aanwijzerGedrukt("primary"):` | Eén uitvoering bij een geaccepteerde primaire druk binnen het beeld. | | `wanneer aanwijzerLosgelaten("primary"):` | Eén uitvoering bij echt loslaten van dezelfde geclaimde aanwijzer. | | `wanneer aanwijzerGeklikt("primary"):` | Eén uitvoering als indrukken en loslaten binnen het beeld plaatsvonden. | `na` vereist een direct eindig getalliteral van 0 tot en met 10 seconden; variabelen en berekende waarden zijn hier niet toegestaan. Een positieve vertraging kleiner dan 1 ms wordt minimaal 1 ms. Berichten en toetsen vereisen een niet-lege tekstliteral. Bij aanwijzers moet de literal exact `"primary"` zijn. Dit zijn gegevenswaarden; schrijf dus niet `"primair"` of `"spatie"`. ```pliro # taal: nl laat klikken = 0 wanneer gestart(): wisScherm("wit") wanneer aanwijzerGeklikt("primary"): zet klikken = klikken + 1 cirkel(aanwijzerX(), aanwijzerY(), 12, "blauw") zeg "Aantal klikken:", klikken ``` Gewone opdrachten initialiseren eerst het programma. Daarna worden scripts coöperatief ingepland. `gestart` begint in bronvolgorde; alle `na`-scripts gebruiken hetzelfde tijdanker na initialisatie. Gelijke deadlines behouden de bronvolgorde; `na(0)` komt achter het gestarte werk. Een timer vuurt eenmaal en houdt daarna zelf geen inactieve sessie open. `wacht` parkeert alleen het actieve script. `zendBericht` zet alle exact passende scripts in bronvolgorde klaar en geeft andere scripts een beurt. Globale variabelen worden gedeeld; lokale variabelen horen bij de afzonderlijke aanroep. Blijvende toets- en aanwijzerscripts houden het programma actief totdat het wordt gestopt, afgesloten of door een fout beëindigd. De host moet iedere vereiste invoercapaciteit ondersteunen. Toetsherhaling van het besturingssysteem veroorzaakt geen nieuwe drukgebeurtenis. Een primaire druk binnen het logische beeld claimt één aanwijzer. Echt loslaten van die aanwijzer levert eerst een loslaatgebeurtenis op, ook buiten het beeld; alleen binnen het beeld volgt ook een klik. Annuleren, verloren capture, extra of dubbele drukken en niet-primaire aanwijzers leveren geen loslaten of klik op. Een al geaccepteerde druk wordt niet teruggenomen. `aanwijzerX()` en `aanwijzerY()` lezen een onveranderlijke opname van de gebeurtenis. Bij druk/klik is x `0..639` en y `0..359`; bij loslaten zijn dit naar beneden afgeronde 32-bits coördinaten met teken, ook buiten het beeld, zonder vastzetten aan de rand. De opname blijft beschikbaar tijdens wachten en functieaanroepen van hetzelfde script; afzonderlijk ingeplande scripts erveren haar niet. Eén soort handler registreren is voldoende. Er zijn nog geen periodieke timers, aanwijzerbeweging, slepen, GPIO-flanken of spritegebeurtenissen. Gebeurtenisbeschrijvingen zijn geen gewone functiewaarden of aanroepen buiten een `wanneer`-kop. Positieve `wacht` en voltooide invoervragen zijn coöperatieve controlepunten. Ze houden Stop en hostgebeurtenissen bruikbaar en beginnen een nieuw instructiebudgetdeel. Wachten in een gebeurtenisscript parkeert alleen dat script. `zendBericht` plant passend werk in en geeft de scheduler een beurt. Plaats een blijvende animatielus in `wanneer gestart():` wanneer andere gebeurtenisscripts tijdens die lus moeten kunnen reageren. ```pliro # taal: nl wanneer gestart(): zolang waar: als toetsIngedrukt("space"): sluitApp() # Werk één beeld bij. wacht(0.04) ``` ## Gerelateerde lemma’s [Syntaxis en waarden](../syntaxis/LEESMIJ.md) · [Ingebouwde functies](../ingebouwde-functies/LEESMIJ.md) · [Programmeergidsen](LEESMIJ.md)