Logo Cusanus Gymnasium Erkelenz
Icon Leitprogramm Informatik

Cusanus-Gymnasium Erkelenz Europaschule

Einführung in die Programmierung mit

Kapitel VII - Ereignisbehandlung
Differenzierungskurs
"Informatik" - Klasse 9 / 10
Gr - 2025 / 2026
Version vom 30.08.2025

Kapitel VII - Ereignisbehandlung

Icon Übersicht

Alle unsere bisherigen Programme haben nach dem Starten eine bestimmte Ausgabe bzw. Grafik oder Figur erzeugt. Das Ergebnis war bei allen Programmen gleich. Auf Wünsche, Eingaben oder Mausklicke der Benutzer wurde während des Programmablaufes nicht reagiert.
Wir wollen im Rahmen dieses Kapitels ein Programm entwickeln, mit dem man ein Turtle-Objekt - abhängig von den gedrückten Tasten - über die Zeichenfläche bewegen kann und entsprechende Figuren oder Muster etc. zeichnen kann.
Dazu werden wir auch eine neue Klasse kennenlernen. Streng genommen ist diese jedoch nicht neu, wir haben bereits seit einiger Zeit mit ihr gearbeitet bzw. sie vor unseren Augen gehabt, ohne es zu wissen. Einige Methoden, die diese Klasse bereitstellt, werden wir nutzen, um auf die angesprochenen Tastatureingaben zu reagieren und am Ende ein einfaches Zeichenprogramm zu erstellen.

Icon Lernziele
Nach der erfolgreichen Bearbeitung der Inhalte des letzten Kapitels kannst du
  • das Objekt der Klasse "Screen" erzeugen lassen bzw. von einer Turtle "abfragen".
  • das Objekt der Klasse "Screen" dazu zu benutzen, generell auf Tastatureingaben zu reagieren.
  • bestimmten Tasten konkrete Methoden oder Funktionen zuordnen.
  • die Schritte, die zur Reaktion auf einen Tastendruck notwendig sind, darstellen.
  • die Turtle über die Zeichenfläche steuern.
  • die interne Bezeichnung einiger besonderer Tasten auf der Tastatur benennen.

Icon Aufgabe 1

Stelle die (graphische) Ausgabe des folgenden Programmes dar. Markiere - wie gehabt - die Position des Turtle-Objektes vor und nach der Ausführung. Erläutere ferner, wann du die entsprechende Ausgabe erhältst.
Hinweise: Bitte verzichte bei dieser Aufgabe vorerst darauf, den Quelltext in den PyScripter / Geany zu übertragen und ausführen zu lassen.

# Autor: Christian Graf
# Datum: 04.04.2011
# Beschreibung: Quelltext zu einer Aufgabe aus Kapitel VII
from turtle import Turtle
myTurtle = Turtle("turtle")
seitenlaenge = 100
def machwas():
    """ Docstring """
    myTurtle.left(90)
    myTurtle.forward(seitenlaenge)
    myTurtle.right(90)
    myTurtle.forward(seitenlaenge)
    myTurtle.right(90)
    myTurtle.forward(seitenlaenge)
    myTurtle.right(90)
    myTurtle.forward(seitenlaenge)
    myTurtle.left(180)
# Ende der Funktion machwas()
machwas()
myTurtle.screen._root.mainloop()
Lösung:
Abbildung
Die hier dargestellte Ausgabe erhält man nach dem Starten des zugehörigen Programmes.
Wenn deine Skizze nicht mit der Vorlage übereinstimmt, versuche deinen Fehler zu finden.

Icon Aufgabe 2

Übertrage das Programm nun in eine neue Datei im PyScripter / in Geany. Speichere es unter einem sinnvollen Dateinamen und führe das Programm aus. Schließe das Fenster der Ausgabe ausnahmsweise einmal nicht, sondern rufe in der im PyScripter verfügbaren Shell die Funktion namens machwas() nochmals auf. Gib deine Beobachtungen an.
Unter Geany kannst du diesen letzten / zusätzlichen Schritt leider nicht durchführen.

Lösung:
Durch die Eingabe
 machwas()
zeichnet das Objekt der Klasse Turtle wiederholt ein Quadrat. Dieses ist allerdings nicht sichtbar, da es genau über das bereits vorhandene Quadrat gezeichnet wird.

Icon Aufgabe 3

Abbildung
Darstellung der zu zeichnenden Figur
Führe das Programm nochmal aus und erweitere die Zeichnung durch die Eingabe von Befehlen in der Shell wie oben dargestellt. Wenn du dich vertan hast, brauchst du nicht von vorne zu beginnen. Mittels des Aufrufes der Methode undo() des Turtle-Objektes kannst du den letzten Schritt rückgängig machen.

Unter Linux / Geany besteht bisher keine Möglichkeit, nach Programmablauf noch einzelne Befehle in Zusammenhang mit diesem Programm auszuführen. Daher musst du hier direkt ein ganzes Programm schreiben, dass die Figur erzeugt.

Lösung:
Selbstkontrolle ;)
In diesem Fall kannst du ganz einfach selber kontrollieren, ob du richtig liegst. Zur Lösung der gestellten Aufgabe gibt es unzählige Wege, das Ziel zu erreichen. Dabei bestehen alle zielführenden Eingaben aus entsprechenden Drehungen nach links oder rechts bzw. Vorwärts- und Rückwärtsbewegungen.
Durch die Eingabe
 myTurtle.undo()
machst du die letzte Aktion der Turtle rückgängig. Achte darauf, dass der Funktionsaufruf aus mehreren Aktionen der Turtle besteht. Entsprechend muss die Methode in diesem Fall mehrmals aufgerufen werden.

Wie wir an den letzten Aufgaben gesehen haben, kann man, auch nachdem alle Anweisungen des eigentlichen Programmes abgearbeitet wurden, noch mit dem erstellten Objekt der Klasse "Turtle" weiterarbeiten. Dazu gibt man die entsprechenden Anweisungen einfach in die im PyScripter verfügbare Shell ein. Daran erkennt man wieder den Vorteil des Live-Modus von Python. Wir können leicht prüfen, ob die neuen Anweisungen zu unserem bereits programmierten Programmteil passen und diese erst nach einem erfolgreichen Test in das Programm übernehmen.
Diese Art, auf Basis des bisherigen Ergebnisses eines Programmes weiter zu arbeiten besteht nur, solange das Ausgabefenster des Turtle-Objektes noch offen ist. Schließen wir dieses, so können wir nicht mehr weiterarbeiten. Dies liegt daran, dass, wenn wir das Fenster schließen, das Objekt der Klasse Turtle zerstört wird und sich nicht mehr im Speicher befindet. Entsprechend können wir dem Objekt also keine Anweisungen mehr geben. Versuchen wir es dennoch, erhalten wir eine Fehlermeldung.

Wir wollen das Programm nun so erweitern bzw. verändern, dass es auf einen Tastendruck, beispielsweise der Taste "q", ein Quadrat zeichnet. Dazu müssen wir uns auch näher mit dem Fenster beschäftigen, in dem das Objekt der Klasse Turtle seine Zeichnungen anfertigt. Dabei handelt es sich - wer hätte es gedacht - ebenfalls um ein Objekt. Es besitzt also ebenfalls - wie Objekte der Klasse Turtle - bestimmte Methoden und Attribute.

Die Klasse "Screen" - eine einmalige Klasse

from turtle import Screen
Screen()
<turtle._Screen object at 0x03572ED0>

Die erste der obigen Anweisungen lädt statt des Bauplanes der Klasse "Turtle" den Bauplan der Klasse "Screen". Anschließend wird ein Objekt der Klasse "Screen" erstellt. Allerdings wird diesem Objekt keine Variable zugewiesen, so dass wir das gerade erzeugte Objekt der Klasse "Screen" nicht ohne weiteres ansprechen können. Darüber, dass die Erstellung eines Objektes der Klasse Screen erfolgreich war, werden wir auf zwei Weisen informiert. Zum Einen erscheint die bereits bekannte Meldung in der Shell. Zum Anderen geht das uns nur zu gut bekannte Fenster auf, in dem ein Objekt der Klasse Turtle seine Zeichnungen anfertigt.

Wir stellen allerdings fest, dass in diesem Fall die Zeichenfläche leer ist. Erst wenn wir zusätzlich den Bauplan der Klasse "Turtle" laden und ein entsprechendes Objekt erstellen, erscheint das Objekt auf unserem Objekt der Klasse "Screen". Wenn du dies ausprobieren möchtest, solltest du die entsprechende Zeichenfläche im Vorfeld nicht schließen.

Bisher wurde das benötigte Objekt der Klasse "Screen" automatisch bei der Erstellung eines Objektes der Klasse "Turtle" mit angelegt und das Objekt der Klasse "Turtle" auf diesem angezeigt. Dementsprechend hätte in unserem kleinen Experiment eben, bei dem wir zuerst ein Objekt der Klasse "Screen" erzeugt haben und anschließend ein Objekt der Klasse "Turtle", doch ein zweites Objekt der Klasse "Screen" erzeugt werden müssen, auf dem die Turtle sichtbar wurde. Dies ist aber offensichtlich nicht der Fall. Es gibt nur eine Zeichenfläche mit einer Turtle. Doch warum ist das so?

Wir können beliebig viele Objekte der Klasse "Turtle" erzeugen, aber höchstens ein Objekt der Klasse "Screen". In dieser Hinsicht ist die Klasse besonders. Selbst wenn wir wie wild mit der Anweisung

Screen()

versuchen würden, neue Objekte zu erzeugen, würde dennoch kein neues Objekt der Klasse erzeugt werden. Es wird immer nur das eine, bereits bestehende, angezeigt. Erkennst du auch an der Ausgabe in der Shell, dass kein neues Objekt erzeugt wurde? Wenn nicht, frage einen Mitschüler oder den Lehrer.

Schaffst du es, dass mehrere Objekte der Klasse Turtle auf dem einzigen Objekt der Klasse "Screen" angezeigt werden? Achte darauf, dass die einzelnen Objekte nicht übereinander liegen.

Icon Wir halten fest:

Bei Objekten der Klasse "Screen" handelt es sich um die Zeichenfläche, auf der sich die Objekte der Klasse "Screen" frei bewegen können und ggf. Spuren hinterlassen. Die Klasse ist in der Hinsicht besonders, als das nur ein Objekt dieser Klasse gleichzeitig existieren kann.
Dies unterscheidet die Klasse beispielsweise von der Klasse "Turtle". Von dieser Klasse können beliebig viele Objekte erzeugt werden.

Icon Aufgabe 4

Überlege dir, welche Methoden und Attribute das Objekt der Klasse "Screen" haben könnte.

Lösung:
Methoden
  • schließen
  • Größe ändern
  • scrollen
  • ...
Attribute
  • Hintergrundfarbe
  • Objekte der Klasse "Turtle" auf der Zeichenfläche
  • Abmessungen
  • Titel
  • ...
Wenn du dir nicht sicher bist, diskutiere deinen Vorschlag mit einem Mitschüler. Kommt ihr zu keinem Ergebnis, versucht euch anderweitig Hilfe zu organisieren.
Beachte, dass die Bezeichnung der Methoden oder Attribute nicht mit den hier angegebenen übereinstimmen muss.

Zwei Methoden der Klasse "Screen" zur Reaktion auf einen Tastendruck

Wenn wir möchten, dass das Objekt der Klasse "Screen" auf einen Tastendruck mit einem bestimmten Verhalten reagiert, sind drei Schritte notwendig:

  1. Wir müssen das Screen-Objekt "anweisen", generell auf das Drücken von Tasten zu reagieren.
    Streng genommen ist die Sache doch etwas komplizierter, als es sich anhört. Zuerst einmal nimmt das Betriebssystem, in den meisten Fällen wird dies Windows sein, den Tastendruck entgegen. Anschließend wird dieser - wenn nötig oder möglich - an die gerade "aktive" Anwendung weitergeleitet. Diese kann dann entsprechend reagieren. Doch mit dem genauen Ablauf wollen wir uns im Rahmen des Leitprogrammes nicht beschäftigen. Uns reicht erst einmal der Hinweis, dass wir das Screen-Objekt auffordern müssen, auf Tastendrücke zu achten, bevor wir das Programm darauf reagieren lassen können.
  2. Für das Überspringen des zweiten Schrittes muss ein Objekt eine Methode haben, die das gewünschte Verhalten realisiert. Gibt es keine entsprechende Methode, so muss im Rahmen dieses zweiten Schrittes alternativ eine eigene Funktion dafür geschrieben werden. Dies ist insbesondere bei komplexen Figuren notwendig, da es hierfür entsprechend selten Methoden eines Objektes gibt. Ebenfalls ist das Schreiben einer Funktion notwendig, wenn wir mehrere Methoden etc. aufrufen wollen.
    Fertige Methoden von Objekten können wir nur verwenden, sofern diese keine Argumente benötigen. Falls unsere Methode einen oder mehrere Parameter benötigt, so müssen wir auch den Umweg über eine Funktion gehen. So können wir beispielsweise die forward()-Methode nicht direkt verwenden, sondern müssen leider den Umweg über eine Funktion gehen.
  3. In einem letzten Schritt müssen wir die Methode oder die Funktion einer entsprechenden Taste zuordnen. Beispiel: Beim Drücken der Pfeil-nach-oben-Taste soll sich das Turtle-Objekt auf dem Bildschirm um 100 Einheiten nach vorne bewegen (forward(100)).

Den ersten Schritt brauchen wir für jedes Programm nur einmalig durchzuführen. Die Schritte zwei und drei müssen wir jedoch für jede Kombination von Tastendruck - Verhalten / Aktion durchführen.

Doch wie sieht das Ganze nun konkret aus. Dazu betrachten wir das folgende - zugegebenermaßen unspektakuläre - Beispielprogramm:

# Christian Graf / 04.04.11 / Demoprogramm für die Ereignisbehandlung (Tastatur)
from turtle import Turtle
myTurtle = Turtle("turtle")
myTurtle.forward(100)
# Linux: Fenster offen lassen ... 
myTurtle.screen._root.mainloop()

Es wird das Modul Turtle geladen, ein Objekt der Klasse "Turtle" mit dem Kostüm "turtle" erzeugt und damit auch ein bzw. das Objekt der Klasse "Screen". Anschließend bewegt sich die Turtle um 100 Bildpunkte vorwärts. Um Schritt 1 umsetzen zu können, benötigen wir Zugriff auf das Screen-Objekt. Durch Aufruf der Methode getscreen() bei unserem erzeugten Turtle-Objekt erhalten wir dieses. Damit wir auch damit arbeiten können, vergeben wir auch für dieses Objekt eine Variable, beispielsweise theScreen.

Icon Aufgabe 5
  1. Formuliere die Anweisung, die der Variablen theScreen das Ergebnis des genannten Methodenaufrufes bei dem Objekt myTurtle liefert.
  2. In welcher Zeile darf die von dir formulierte Anweisung frühestens stehen?
Lösung:
  1. theScreen = myTurtle.getscreen()
    Zur Erklärung: Wir rufen die Methode getscreen(), die das Objekt unter dem Namen myTurtle bereitstellt, auf. Das Ergebnis (also das Objekt der Klasse "Screen") speichern wir unter der Variablen theScreen.
  2. Das Objekt der Klasse "Turtle" muss bereits erzeugt sein, da es sonst (noch) kein Objekt der Klasse "Screen" gibt. Entsprechend darf die Anweisung frühestens in Zeile 04 stehen.
    # Christian Graf / 04.04.11 / Demoprogramm für die Ereignisbehandlung (Tastatur)
    from turtle import Turtle
    myTurtle = Turtle("turtle")
    theScreen = myTurtle.getscreen()
    myTurtle.forward(100)
    # Linux: Fenster offen lassen ... 
    myTurtle.screen._root.mainloop()
    

Nun können wir dem Objekt theScreen die Anweisung geben, auf Tastendrücke zu reagieren. Dazu müssen wir die vom Objekt bereitgestellte Methode listen() aufrufen. Die zugehörige Anweisung lautet - wie bei einem Methodenaufruf üblich:

theScreen.listen()

Ergänze diese Anweisung nun an geeigneter Stelle in deinem Programm. Dies ist frühestens nach der Festlegung bzw. Erzeugung der Variablen theScreen der Fall. Wenn du genau hinschaust, siehst du nach einer wiederholten Ausführung des Programmes einen kleinen Unterschied am Rand des Fensters.

Abbildung
Darstellung des veränderten Randes des Screen-Objektes

Methode + Taste = Reaktion

Den ersten Schritt hätten wir damit erledigt. Diesen brauchen wir in unserem Programm - selbst wenn wir eine Reaktion für alle möglichen Tasten der Tastatur festlegen - nur einmal durchzuführen. Das reicht, um das ganze Programm entsprechend einzustellen.

Starte nun das Programm aus der letzten Aufgabe. Schließe das entsprechende Fenster, also das Objekt der Klasse "Screen" noch nicht. Gib nun in der Shell die folgende Anweisung ein:

theScreen.bye()

Überlege vorher, welche Reaktion du vermutest.

Die entsprechende Methode des Objektes schließt das Fenster. Wir wollen nun, dass bei einem Drücken der "Escape"-Taste (links oben auf der Tastatur zu finden, trägt die Beschriftung 'esc') genau diese Methode aufgerufen wird. Wir halten fest:
Tastendruck: "Escape"
Reaktion: Schließen des Fensters (Aufruf der Methode bye() des Objektes theScreen)

Für eine entsprechende Realisierung stellt das Screen-Objekt eine weitere Methode bereits, die Tastendruck und Reaktion "verbindet". Dies trägt - sinnigerweise - den Namen onkey(). Ferner benötigt die Methode zwei Argumente:

  1. Mittels des ersten Argumentes legt man die Methode (inkl. zugehörigem Objekt) oder die Funktion fest, die ausgeführt werden soll.
    Hierbei muss man allerdings beachten: Die Klammern, die man normalerweise am Ende der Anweisung ergänzt, müssen in diesem Fall weggelassen werden!
  2. Das zweite Argument spezifiziert die entsprechende Taste, bei deren Druck die Methode aufgerufen werden soll.
    Diese wird als Zeichenkette übergeben, also beispielsweise "a" oder "A".

Möchten wir also, dass die Methode bye() des Screen-Objektes aufgerufen wird, wenn wir die Escape-Taste drücken, so lauten die Argumente für die onkey()-Methode des Screen-Objektes:

  1. theScreen.bye
  2. "Escape"

Entsprechend lautet dann die vollständige Anweisung:

theScreen.onkey(theScreen.bye,"Escape")
Icon Aufgabe 6

Integriere die obige Anweisung in das Programm und teste die neue Funktionalität.

Lösung:
# Christian Graf / 04.04.11 / Demoprogramm fuer die Ereignisbehandlung (Tastatur)
from turtle import Turtle
myTurtle = Turtle("turtle")
theScreen = myTurtle.getscreen()
theScreen.listen()
theScreen.onkey(theScreen.bye,"Escape")
myTurtle.forward(100)
# Linux: Fenster offen lassen ... 
myTurtle.screen._root.mainloop()

Funktion + Taste = Reaktion

Einzelne Methoden können wir bereits einer Taste zuordnen. Dies geht allerdings nur, solange diese keine Argumente benötigen, da wir die Klammern weglassen müssen. Entsprechend erhalten wir keine direkte Möglichkeit, solche Methoden aufzurufen. Doch wie können wir nun einen Methodenaufruf mit einem notwendigen Argument, wie beispielsweise

myTurtle.forward(100)

einer Taste zuordnen?

Dazu müssen wir vorher noch eine Funktion definieren, die die Methode für uns aufruft. Beispielsweise:

def vor():
    """ bewegt das Objekt um 100 Pixel vor """ 
    myTurtle.forward(100)

Jetzt können wir, wie gehabt, die Funktion an eine Taste binden. Wichtig ist, dass wir auch hier die Klammern im Anschluss an den Funktionsnamen - die wir sonst immer mit angeben müssen - weglassen.

Icon Aufgabe 7

Integriere die obigen Anweisungen in das Programm und teste die neue Funktionalität.
Binde die Funktion an die Taste "Up". Dieser String bezeichnet die Pfeiltaste nach oben auf deiner Tastatur.

Lösung:
# Christian Graf / 04.04.11 / Demoprogramm für die Ereignisbehandlung (Tastatur)
# Vorbereitungen
from turtle import Turtle
myTurtle = Turtle("turtle")
# Screen holen
theScreen = myTurtle.getscreen()
# Screen für Eingabe vorbereiten
theScreen.listen()
# Funktionen
def vor():
    """ bewegt das Objekt um 100 Pixel vor """ 
    myTurtle.forward(100)
# Bindung Fkt - Taste
theScreen.onkey(theScreen.bye,"Escape")
theScreen.onkey(vor,"Up")
myTurtle.forward(100)
# Linux: Fenster offen lassen ... 
myTurtle.screen._root.mainloop()

Laufen und Drehen per Tastatursteuerung

Icon Aufgabe 8

Schreibe drei weitere Funktionen, die das Turtle-Objekt rückwärts bewegen bzw. um einen bestimmten Winkel nach rechts oder links drehen. Binde anschließend die Funktionen an die Tasten "Down", "Left" und "Right". Das sind die Bezeichnungen für die anderen Pfeiltasten auf deiner Tastatur.

Lösung:
# Christian Graf / 04.04.11 / Demoprogramm fuer die Ereignisbehandlung (Tastatur)
# Vorbereitungen
from turtle import Turtle
myTurtle = Turtle("turtle")
# Screen holen
theScreen = myTurtle.getscreen()
# Screen fuer Eingabe vorbereiten
theScreen.listen()
# Funktionen
def vor():
    """ vorwaertsbewegung """
    myTurtle.forward(100)
def runter():
    """ rueckwaertsbewegung """
    myTurtle.backward(100)
def links():
    """ linksdrehung """
    myTurtle.left(10)
def rechts():
    """ rechtsdrehung """
    myTurtle.right(10)
# Bindung Fkt - Taste
theScreen.onkey(theScreen.bye,"Escape")
theScreen.onkey(vor,"Up")
theScreen.onkey(runter,"Down")
theScreen.onkey(links,"Left")
theScreen.onkey(rechts,"Right")
myTurtle.forward(100)
# Linux: Fenster offen lassen ... 
myTurtle.screen._root.mainloop()

Ein simples Malprogramm

Im letzten Schritt wollen wir unser bisheriges Programm so umbauen, dass die Turtle den Stift auf Tastendruck der Leertaste ("space") hochheben bzw. wieder ablassen kann. Auf diese Weise können wir die Turtle über die Zeichenfläche bewegen und dabei Bilder zeichnen.

Dazu brauchen wir eine weitere Funktion, die intern unterscheidet, ob der Stift unten oder oben ist und ihn dann entsprechend hochhebt oder absenkt. Diese Formulierung schreit doch buchstäblich nach einer Verzweigung. Doch wie können wir unterscheiden, ob der Stift oben oder unten ist?
Dazu stellt die Turtle eine Abfrage bereit. Der Aufruf der Methode isdown() bei einem konkreten Turtle-Objekt gibt an, ob der Stift oben oder unten ist. Dabei kann die Abfrage entweder True sein, dann ist der Stift entsprechend unten oder False, dann ist der Stift angehoben. Für unser Programm würde die erste Zeile der Verzweigung also wie folgt lauten:

if myTurtle.isdown():
Icon Aufgabe 9
  1. Vervollständige die beiden Teile der Verzweigung. Überlege dir, was in welchem Teil geschehen muss.
  2. Schreibe für die Verzweigung eine Funktion, so dass du diese an eine Taste, hier "space" (Leertaste) binden kannst.
  3. Teste dein Programm.
Lösung:
# Christian Graf / 04.04.11 / Demoprogramm fuer die Ereignisbehandlung (Tastatur)
# Vorbereitungen
from turtle import Turtle
myTurtle = Turtle("turtle")
# Screen holen
theScreen = myTurtle.getscreen()
# Screen fuer Eingabe vorbereiten
theScreen.listen()
# Funktionen
def vor():
    """ vorwaertsbewegung """
    myTurtle.forward(100)
def runter():
    """ rueckwaertsbewegung """
    myTurtle.backward(100)
def links():
    """ linksdrehung """
    myTurtle.left(10)
def rechts():
    """ rechtsdrehung """
    myTurtle.right(10)
def switch():
    """ schaltet den Stift hoch / runter """
    if myTurtle.isdown():
        myTurtle.penup()
    else:
        myTurtle.pendown()
# Bindung Fkt - Taste
theScreen.onkey(theScreen.bye,"Escape")
theScreen.onkey(vor,"Up")
theScreen.onkey(runter,"Down")
theScreen.onkey(links,"Left")
theScreen.onkey(rechts,"Right")
theScreen.onkey(switch,"space")

myTurtle.forward(100)
# Linux: Fenster offen lassen ... 
myTurtle.screen._root.mainloop()

Icon Aufgabe 10

Erweitere das Programm um eine Funktion zum Zeichnen eines Quadrates. Binde dieses an die Taste "q".
Ändere die Taste in "Q". Stelle deine Beobachtungen dar.

Lösung:
# Christian Graf / 04.04.11 / Demoprogramm fuer die Ereignisbehandlung (Tastatur)
# Vorbereitungen
from turtle import Turtle
myTurtle = Turtle("turtle")
# Screen holen
theScreen = myTurtle.getscreen()
# Screen fuer Eingabe vorbereiten
theScreen.listen()
# Funktionen
def vor():
    """ vorwaertsbewegung """
    myTurtle.forward(100)
def runter():
    """ rueckwaertsbewegung """
    myTurtle.backward(100)
def links():
    """ linksdrehung """
    myTurtle.left(10)
def rechts():
    """ rechtsdrehung """
    myTurtle.right(10)
def switch():
    """ schaltet den Stift hoch / runter """
    if myTurtle.isdown():
        myTurtle.penup()
    else:
        myTurtle.pendown()
def quadrat():
    """ zeichnet ein Quadrat """
    for i in range(4):
        myTurtle.forward(100)
        myTurtle.left(90)
# Bindung Fkt - Taste
theScreen.onkey(theScreen.bye,"Escape")
theScreen.onkey(vor,"Up")
theScreen.onkey(runter,"Down")
theScreen.onkey(links,"Left")
theScreen.onkey(rechts,"Right")
theScreen.onkey(switch,"space")
theScreen.onkey(quadrat,"q")
myTurtle.forward(100)
# Linux: Fenster offen lassen ... 
myTurtle.screen._root.mainloop()
Ändert man die Taste, so reagiert das Programm nur noch auf ein großes Q. Entsprechend stellen wir fest, dass es auch hier einen Unterschied zwischen Groß- und Kleinschreibung gibt.
Dies kann man beispielweise dazu nutzen, zwei unterschiedlich große Quadrate zu zeichnen.

Wechseln der Farbe

Schön wäre es nun noch, wenn wir nicht nur den Stift anheben könnten, sondern zusätzlich auch noch zwischen zwei Farben, beispielsweise schwarz ("black") und rot ("red") wechseln könnten. Benenne dazu bitte die Funktion switch() zum Anheben oder Absenken des Stiftes um in switchpen(), um Verwechslungen zu vermeiden. Achte darauf, dass du dafür an zwei Stellen in deinem Programm etwas ändern musst.

Starte nun nochmal unser bisheriges Malprogramm und lasse das Fenster offen. Gib in der zugehörigen Shell

myTurtle.pencolor()

ein. Als Ausgabe erhalten wir:

'black'

Mit dieser Methode kann man offensichtlich die Stiftfarbe abfragen. Doch die Methode kann noch weit mehr:

myTurtle.pencolor("red")

weist die Turtle an, die Stiftfarbe auf Rot ("red") zu ändern. Eine entsprechende Abfrage liefert nun das Ergebnis

'red'

Wir wollen mittels dieser Methode des Turtle-Objektes nun eine Funktion switchcolor() programmieren, die bei einem Druck der Taste "c" die Stiftfarbe wechselt. Der Aufbau der Funktion ist vergleichbar mit der switchpen()-Funktion: Wir fragen ab, ob die Stiftfarbe schwarz ist, wenn ja, wechseln wir zu Rot. Ist dies nicht der Fall, so wechseln wir die Stiftfarbe auf Schwarz. Achte darauf, dass du bei einem Vergleich zweier Zeichenketten das doppelte Gleichheitszeichen und nicht den Zuweisungsoperator (einfaches Gleichheitszeichen) verwenden musst.

Icon Aufgabe 11

Formuliere die obige verbale Beschreibung der Funktion als Quelltext. Ordne der Funktion auch die genannte Taste zu.

Lösung:
# Christian Graf / 04.04.11 / Demoprogramm fuer die Ereignisbehandlung (Tastatur)
# Vorbereitungen
from turtle import Turtle
myTurtle = Turtle("turtle")
# Screen holen
theScreen = myTurtle.getscreen()
# Screen fuer Eingabe vorbereiten
theScreen.listen()
# Funktionen
def vor():
    """ vorwaertsbewegung """
    myTurtle.forward(100)
def runter():
    """ rueckwaertsbewegung """
    myTurtle.backward(100)
def links():
    """ linksdrehung """
    myTurtle.left(10)
def rechts():
    """ rechtsdrehung """
    myTurtle.right(10)
def switchpen():
    """ schaltet den Stift hoch / runter """
    if myTurtle.isdown():
        myTurtle.penup()
    else:
        myTurtle.pendown()
def switchcolor():
    """ schaltet die Stiftfarbe zwischen schwarz und rot um """
    if myTurtle.pencolor()=="black":
        myTurtle.pencolor("red")
    else:
        myTurtle.pencolor("black")
def quadrat():
    """ zeichnet ein Quadrat """
    for i in range(4):
        myTurtle.forward(100)
        myTurtle.left(90)
# Bindung Fkt - Taste
theScreen.onkey(theScreen.bye,"Escape")
theScreen.onkey(vor,"Up")
theScreen.onkey(runter,"Down")
theScreen.onkey(links,"Left")
theScreen.onkey(rechts,"Right")
theScreen.onkey(switchpen,"space")
theScreen.onkey(switchcolor,"c")
theScreen.onkey(quadrat,"q")
myTurtle.forward(100)
# Linux: Fenster offen lassen ... 
myTurtle.screen._root.mainloop()

Zwei Farben sind für interessante Zeichnungen oder Gemälde in den meisten Fällen zu wenig. Die folgende Version der Funktion switchcolor() ändert diesen Umstand.

def switchcolor():
    """ schaltet die Stiftfarbe ... """
    if myTurtle.pencolor()=="black":
        myTurtle.pencolor("red")
    else:
        if myTurtle.pencolor()=="red":
            myTurtle.pencolor("blue")
        else:
            if myTurtle.pencolor()=="blue":
                myTurtle.pencolor("green")
            else:
                myTurtle.pencolor("black")
  • Kannst du den Ablauf der Funktion erklären?
  • In welcher Reihenfolge werden die Farbe gewechselt?
  • Um welche Farben handelt es sich?

Wenn du Probleme hast, wende dich an einen Mitschüler.

Übrigens, im Additum zu Kapitel VI wird eine Möglichkeit vorgestellt, solche verschachtelten Verzweigungen geschickter und leichter lesbar darzustellen.

Wenn du die Lernfortschrittskontrolle und den Kapiteltest bestanden hast, kannst du gerne - sofern nicht bereits geschehen - die Addita zu den einzelnen Kapiteln noch durcharbeiten. Dort werden einzelne Inhalte des Leitprogramms noch weiter vertieft bzw. erweitert.

Weiter geht's mit der Lernfortschrittskontrolle zu Kapitel VII.