Jython

9. Maus-Events

Die Ereignissteuerung ist ein wichtiges Programmierkonzept, das insbesondere bei Programmen mit einer grafischen Benutzeroberfläche zur Anwendung kommt, die auf Mausklicks, Drücken von Tastaturtasten oder (bei Smartphones) Touch-Events reagieren.

Bei den Mausevents verwendet man die folgende Programmiertechnik:
Man definiert in einer Funktion (der soganannten Callbackfunktion), was beim Drücken einer Maustaste geschehen soll. Diese Funktion wird im eigenen Programmcode nie explizit aufgerufen, sondern beim Auftreten eines Mausevents automatisch vom System. Dazu muss man dem System bekannt geben, wie sie heisst.  Man nennt dies auch "Registrieren des Callbacks").

Beispiel 1: Mit Mausklicks Kreise zeichnen
Die Callbackfunktion onMousePressed(x, y) zeichnet an der Position des Mausklicks einen kleinen Kreis. Diese Funktion wird beim Aufruf von makeGPanel() mit einem sogenannten benannten Parameter mousePressed = onMousePressed registriert.

# Gp9a.py

from gpanel import *

def onMousePressed(x, y):
    pos(x, y)    
    fillCircle(1)

makeGPanel(0, 20, 0, 20, mousePressed = onMousePressed)
setColor("cyan")
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

Das Drücken einer Maustaste kann man mit zwei verschiedenen Callbacks erfassen: einem Press-Event oder einem Click-Event. Der Click-Event wird erst ausgelöst, nachdem die Taste wieder losgelassen wird, der Press-Event bereits beim Drücken der Maustaste. Der Click-Event wird mit dem Parameter mouseClicked registriert.

Der Name der Callbackfunktion kann frei gewählt werden (er könnte hier auch drawCircle heissen). Der Name des benannten Parameters, mit welchem die Callbackfunktion in makeGPanel() registriert wird, muss aber mousePressed oder mouseClicked heissen.

 

Beispiel 2: Eine Mausbewegung erfassen

Ein Callback, der mit dem Parameter mouseMoved registriert wird, reagiert auf die Mausbewegungen.
Falls er mit dem Parameter mouseDragged registriert wird, reagiert er auf Mausbewegungen mit gedrückter Maustaste.

Im Beispiel entstehen durch eine Mausbewegung mit gedrückter Maustaste lustige röhrenartige Figuren.

# Gp9b.py

from gpanel import *      

def onMouseDragged(x, y):
    pos(x, y)
    setColor("cyan")
    fillCircle(.04) 
    setColor("black")
    circle(.04)  

makeGPanel(mouseDragged = onMouseDragged)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

mouseDragged kann durch mouseMoved ersetzt werden. Dann wird bereits ohne Drücken der Maustaste gezeichnet.


Beispiel 3
: Freihandzeichnen mit gedrückter Maustaste
Mit Mausevents kann man ein einfaches Zeichnungsprogramm erstellen. Dazu verwendet man die Funktion draw(x, y) die bei jedem Aufruf der Callbackfunktion onMouseDragged() eine Linie zur aktuellen Mausposition zeichnet (und den Grafikcursor auf x, y setzt). Den Callback onMousePressed() benötigt man, um den Grafikcursor jeweils an die aktuelle Mausposition zu setzten.

# Gp9c.py

from gpanel import *

def onMousePressed(x, y):
    pos(x, y)

def onMouseDragged(x, y):
    draw(x, y)

makeGPanel(mousePressed = onMousePressed, 
           mouseDragged = onMouseDragged)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

draw(x, y) : Bewegt den Grafikcursor zum Punkt (x, y) und zeichnet dabei eine Line von der alten zur neuen Position
makeGPanel() Die beiden Callbackfunktionen werden beim Erzeugen des GPanels mit benannten Parametern gleichzeitig registriert. Bei benannten Parametern spielt die Reihenfolge keine Rolle


Beispiel 4
: Mit Mausklicks geschlossene Figuren füllen
Im Beispiel wird zuerst ein 8x8 Gitter gezeichnet. Mit einem Mausklick sollen danach die Gitterfelder mit der Funktion fill() rot gefärbt werden.

# Gp9d.py

from gpanel import *

def drawGrid():
    for k in range(8):
        for i in range(8):
            rectangle(i, k, i + 1, k + 1)  
    
def onMousePressed(x, y):
    fill(x, y, "white", "red")   

makeGPanel(-1, 9, -1, 9, mousePressed = onMousePressed)
drawGrid()
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

fill(x, y, "white", "red"): Die geschlossene Figur (ein Quadrat), in der sich der Punkt (x, y) befindet, wird gefärbt. white ist die alte Farbe, red die neue Farbe.


Beispiel 5
: Eine einfache Version des Spiels Four-in-a-Row
Das bekannte Spiel hat folgende Spielregeln:
Zwei Spieler wählen abwechslungsweise per Mausklick ein leeres Feld in einem 7x7 Gitter, wobei diese beim  1. Spielers rot und beim 2. Spielers grün gefärbt werden. Dabei muss man die Spalten von unten auffüllen. Der Spieler, der zuerst 4 eigene Felder in einer Zeile, Spalte oder Diagonale setzen kann, hat gewonnen. (Das hier gezeigte Programm enthält keine Überprüfung von Eingabefehlern und dem Ende des Spiels.)

# Gp9e.py

from gpanel import *

def drawGrid():
    for k in range(8):
        for i in range(8):
            rectangle(i, k, i + 1, k + 1)  
    
def onMousePressed(x, y):
    if isLeftMouseButton():
        fill(x, y, "white", "red")   
    if isRightMouseButton():    
        fill(x, y, "red", "white")   

makeGPanel(-1, 9, -1, 9, mousePressed = onMousePressed)
drawGrid()
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

isLeftMouseButton(): Gibt True zurück, wenn die linke Maustaste gedrückt wurde
isRightMouseButton(): Gibt True zurück, wenn die rechte Maustaste gedrückt wurde


Beispiel 6
: Einfache Version des Spiels Four-in-a-Row
Diese einfache Version des bekanntes Spiels implementiert folgende Spielregeln:
Zwei Spieler wählen abwechslungsweise per Mausklick die Felder im 7x7 Gitter, wobei die Felder des 1. Spielers rot und die des 2. Spielers grün gefärbt werden. Dabei muss man die Spalten von unten auffüllen. Der Spieler, der zuerst 4 Felder in einer Zeile, Spalte oder Diagonale setzen kann, hat gewonnen.

# Gp9e.py

from gpanel import *

def drawBoard():
    for k in range(8):
        line(0, k, 7, k )  
    for i in range(8):
        line(i, 0, i, 7 )
        
def onMousePressed(x, y):
    global player
    if player == 1:
        fill(x, y, "white", "red")
        player = 2
    elif player == 2:
        fill(x, y, "white", "green")
        player = 1        

makeGPanel(-1, 8, -1, 8, mousePressed = onMousePressed)
drawBoard()
player = 1
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

if player == 1: Damit die Felder abwechslungsweise rot oder grün gefärbt werden, muss man bei jedem Mausklick überprüfen, ob der Spieler 1 oder 2 am Zug ist. Der aktuelle Zustand wird in der Variablen player gespeichert. Ist der Wert 1, wird rot gefärbt und dann der Wert auf 2 gesetzt, umgekehrt wird grün gefärbt und der Wert auf 1 gesetzt
global player Um den Wert der Variablen, die im Hauptprogramm definiert ist, in einer Funktion zu ändern, muss sie als global deklariert werden




Aufgaben: Serie 9

1)


An der Position des Mausklicks entsteht ein kleiner Punkt und eine Linie zum vorangehenden Punkt.

 


2)


Ersetze im Beispiel 2 die Callbackfunktion onMouseDragged() durch onMouseMoved(x, y) und registriere sie mit dem Parameter mouseMoved. Dann kannst du die Röhren ohne Drücken der Maustaste zeichnen.


 


3)


Im Kapitel Funktionen hast du gelernt, wie man Sterne zeichnet. Bei jedem Mausklick soll an der Mausposition ein Stern entstehen.



 


4)


Programmiere eine einfache Version des Spiels Tic-Tac-Toe mit folgenden Spielregeln:
Zwei Spieler markieren abwechslungsweise Felder in einem 3x3 Gitter, wobei diese beim 1. Spieler rot und beim zweiten Spieler grün gefärbt werden. Wer zuerst drei Felder in einer Zeile, Spalte oder Diagonale belegen kann, hat gewonnen.