deutsch     english     français     Drucken

 

2.10 EREIGNISSTEUERUNG

 

 

EINFÜHRUNG

 

Bisher bestand ein Programm aus einem einzigen Ablaufstrang, in dem eine Anweisung um die andere mit möglichen Verzweigungen und Wiederholungen ausgeführt wird. Klickst du eine Maustaste, so weisst du aber nicht, wo sich dein Programm eben gerade befindet. Um das Klicken im Programm zu erfassen,  muss daher ein neues Programmierkonzept verwendet werden, die Ereignissteuerung. Hier das Prinzip:

Du definierst eine Funktion mit irgendeinem Namen, z.B. onMouseHit(), die im Programm nirgends explizit aufgerufen wird. Nun verlangst du vom Computer, dass er diese Funktion aufrufen soll, wenn die Maustaste geklickt wird. Du sagst also im Programm: Wann immer die Maus geklickt wird, führe onMouseHit() aus.

PROGRAMMIERKONZEPTE: Ereignisgesteuertes Programm, Mausevent

 

 

MAUSEVENTS

 

Das neue Konzept ist in Python sehr einfach umzusetzen. Im ersten ereignisgesteuerten Programm soll im Hauptteil die Turtle zuerst eine lustige Figur zeichnen. Nachher willst du diese noch verschönern, indem du bestimmte Bereiche mit einem Mausklick einfärbst.

Du schreibst dazu die Funktion onMouseHit(x, y), die dir die x- und y-Koordinate des Mausklicks liefert, und führst darin mit fill(x, y) ein Floodfill (Füllen eines geschlossenen Bereichs) aus.

Das Wichtige dabei ist aber, dass du dem System mitteilst, dass es die Funktion onMouseHit() aufrufen soll, wenn die Maustaste gedrückt wird. Dazu verwendest du beim Aufruf von makeTurtle() den Parameter mit dem festgelegten Namen mouseHit und übergibst ihm den Namen deiner Funktion.

Damit die Zeichnung rasch erstellt wird, kannst du die Turtle mit hideTurtle() verstecken.

 
from gturtle import *

def onMouseHit(x, y):
    fill(x, y)      
        
makeTurtle(mouseHit = onMouseHit)
hideTurtle()
addStatusBar(30)
setStatusText("Click to fill a region!")
  
repeat 12:
    repeat 6:
        forward(80)
        right(60)
    left(30)      
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

MEMO

 

Programmtechnisch wird das  Konzept der ereignisgesteuerten Programmierung bei unserer Turtle so umgesetzt, dass du eine Funktion schreibst, die beim Auftreten des Ereignisses aufgerufen werden soll. Du teilst dies dem System mit, indem du diesen Funktionsnamen als Parameter von makeTurtle() übergibst. Dabei verwendest du die Schreibweise parameter_name = parameter_wert.

Du kannst die Füllfarbe mit setFillColor() deinen Wünschen anpassen.

Wichtige Informationen für den Benutzer kannst du in einer Statuszeile ausschreiben, die mit addStatusBar(n) unten am Turtlefenster erscheint. Die Zahl n gibt die Höhe dieser Textzeile an (in Pixel).

 

 

ZEICHNEN PER MAUSKLICK

 

Die Turtle soll an der Stelle des Mausklicks einen Strahlenstern zeichnen. Du schreibst dazu die Funktion onMouseHit(x, y), mit der du die Turtle anweist, wie sie den Stern zeichnen soll. Damit onMouseHit() beim Mausklick aufgerufen wird, übergibst du in makeTurtle() dem Parameternamen mouseHit diesen Funktionsnamen onMouseHit.

 
from gturtle import *

def onMouseHit(x, y):
    setPos(x, y)
    repeat 6:
        dot(40)
        forward(60)
        back(60)
        right(60)

makeTurtle(mouseHit = onMouseHit)
speed(-1)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

MEMO

 

Das Programm hat einen Schönheitsfehler: Wenn du bereits wieder klickst, während die Turtle noch am Zeichnen eines Sterns ist, so zeichnet sie diesen Stern nicht fertig, sondern beginnt mit dem Zeichnen des neuen Sterns. Dabei führt sie aber die Befehle des alten Sterns auch noch weiter, wodurch der neue Stern falsch gezeichnet wird.

Dieses Falschverhalten ist offenbar darauf zurück zu führen, dass bei jedem Klick die Funktion onMouseHit() aufgerufen und ausgeführt wird, auch wenn die vorhergehende Ausführung noch nicht beendet ist. Um dies zu verhindern, verwendest du an Stelle des Parameters mit dem Namen mouseHit den Parameter mit dem Namen mouseHitX.

 

 

TURTLE VERFOLGT MAUS

 

Du möchtest, dass die Turtle ständig der Maus folgt. Dazu kannst du den Mausklick nicht gebrauchen, sondern musst die Mausbewegung als Ereignis betrachten. makeTurtle() kennt den Parameter mouseMoved, dem du eine Funktion übergeben kannst, die bei jeder Verschiebung der Maus aufgerufen wird.

Die Funktion onMouseMoved(x, y) erhält als Parameterwerte die aktuellen Cursorkoordinaten.

 
from gturtle import *

def onMouseMoved(x, y):
    setHeading(towards(x, y))
    forward(10)
      
makeTurtle(mouseMoved = onMouseMoved)
speed(-1)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

MEMO

 

Neben mouseHit und mouseHitX stehen dir für das Erfassen von Mausevents in makeTurtle() weitere Parameter zur Verfügung.

mousePressed Maustaste wird gedrückt
mouseReleased Maustaste wird losgelassen
mouseClicked Maustaste wird gedrückt und losgelassen
mouseDragged Maus wird mit gedrückter Taste bewegt
mouseMoved Maus wird bei nicht gedrückter Taste bewegt
mouseEntered Maus tritt in das Turtlefenster ein
mouseExited Maus tritt aus dem Turtlefenster aus

Du kannst auch mehrere Parameter gleichzeitig verwenden, also beispielsweise die zwei Funktionen onMousePressed() sowie onMouseDragged() angeben:

makeTurtle(mousePressed = onMousePressed, mouseDragged = onMouseDragged)

Mit isLeftMouseButton() bzw. isRightMouseButton() findest du heraus, welche Maustaste gedrückt wurde.

Es gibt bei diesen Events einen wichtigen Unterschied zu mouseHit: Die Bewegung der Turtle ist während der Ausführung der Funktion nicht sichtbar. Du solltest also entweder die Turtle mit speed(-1) auf hohe Geschwindigkeit setzen oder mit hideTurtle() verstecken.


 
from gturtle import *

def onMousePressed(x, y):
    moveTo(x, y)
      
makeTurtle(mousePressed = onMousePressed)
#speed(-1)
#hideTurtle()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

TASTATUREVENTS

 

Auch das Drücken einer Taste auf der Tastatur löst einen Event aus. Um ihn "abzufangen", übergibst du wie vorhin mit Mausevents in makeTurtle() dem System den Namen der Funktion, hier onKeyPressed(), die es aufrufen soll, wenn das Ereignis eintritt. Dazu verwendest du den vordefinierten Parameternamen keyPressed. Beim Aufruf erhält deine Funktion eine Zahl key, aus der du die Taste bestimmen kannst, die gedrückt wurde. (Die Werte kannst du durch einige Versuche selbst herausfinden.) In deinem Programm bewegt sich die Turtle ständig um 10 Schritte vorwärts. Du kannst aber ihre Richtung mit den Cursortasten in den vier Himmelsrichtungen verändern. Damit die Turtle das Fenster nicht verlässt, verwendest du den Wrap-Modus.

 
from gturtle import *

LEFT = 37
RIGHT = 39
UP = 38
DOWN = 40

def onKeyPressed(key):
   if key == LEFT:
      setHeading(-90)
   elif key == RIGHT:
      setHeading(90)
   elif key == UP:
      setHeading(0)
   elif key == DOWN:
      setHeading(180)

makeTurtle(keyPressed = onKeyPressed)
wrap()
while True:
    forward(10)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

AUFGABEN

 

1.

Zeichne mit einer Wiederholstruktur den nebenstehenden Stern und fülle ihn mit Mausklicks nach deinem Geschmack aus.
 

2.
Du kannst die Turtle dazu verwenden, ein Programm zum Freihandzeichen zu erstellen. Dabei wird der Zeichenstift mit mit dem Press-Event gesetzt mit dem Drag-Event bewegt.  
3.
Mit gedrückter linken Maustaste zeichnest du eine beliebige Figur. Mit einem Klick auf die rechte Maustaste kannst du ein Gebiet ausfärben.  
4.

Gehe von Aufgabe 2 aus und erstelle ein Programm, mit dem du mit gezogener Maus eine kaleidoskopische Figur zeichnen kannst, d.h. die mit der (versteckten) Turtle erzeugte Linie wird gleichzeitig in allen 4 Quadraten gezeichnet. Um ein Linienstück zu zeichnen, kannst du die folgende Funktion definieren:

def line(x1, y1, x2, y2):
    setPos(x1, y1)
    moveTo(x2, y2)

 


5.

Ergänze das Programm mit der Tastatursteuerung so, dass beim Drücken der Leertaste (Key Code 32) eine geschlossene Fläche, in der sich die Turtle gerade befindet, gefüllt wird. Zeichne damit einen gefüllten Buchstaben.

   

 

 

 

ZUSATZSTOFF


 

DEIN PERSÖNLICHES MAUSBILD

 

Du kannst das Bild des Mauscursors deinen eigenen Vorstellungen anpassen und damit dem Programm ein spezielles Aussehen geben. Dazu verwendest du den Befehl setCursor() und übergibst  einen der Werte aus der untenstehenden Tabelle. Du kannst sogar ein eigenes Mausbild verwenden, wenn du setCustomCursor() den Pfad deiner  Bilddatei übergibst. Übliche Mauszeiger sind 32x32 Pixel gross und haben einem transparenten Hintergrund. Sie sollten im gif oder png-Format gespeichert sein. In der Distribution von TigerJython stehen dir bereits zwei Cursorbilder pencil.gif und cutemouse.gif im Verzeichnis sprites zur Verfügung.

 

Das oben gezeigte Verfolgungsprogramm kannst du jetzt mit cuteturtle oder deiner eigenen Mausfigur verschönern, wobei du auch mit moveTo() dafür sorgst, dass die Turtle sich immer bis zur Maus bewegt.

from gturtle import *

def onMouseMoved(x, y):
      moveTo(x, y)
      
makeTurtle(mouseMoved = onMouseMoved)
setCustomCursor("sprites/cutemouse.gif")
speed(-1)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

MEMO

 

Mit speed(-1) unterbindest du die Animation der Turtle, wodurch das Zeichnen mit moveTo() schneller erfolgt.

Mögliche Parameter von setCursor():

Parameter Ikone
Cursor.DEFAULT_CURSOR Standard-Ikone
Cursor.CROSSHAIR_CURSOR Fadenkreuz
Cursor.MOVE_CURSOR Verschiebungs-Cursor (Kreuzpfeile)
Cursor.TEXT_CURSOR Text-Cursor (vertikaler Strich)
Cursor.WAIT_CURSOR Geduld-Cursor

Das Verzeichnis sprites in der Pfadangabe von setCustomCursor() ist im Verzeichnis, in dem sich dein Programm befindet [mehr... Es kann sich auch um ein Unterverzeichnis im Verzeichnis gamegrid im UserHome handeln.
Du kannst auch einen voll qualifizierten Dateinamen verwenden, z.B. unter Windows d:/myturtles/mycursor.gif.
]