2.10 EVENT CONTROL

 

 

INTRODUCTION

 

So far we have only seen a programs with a single strand of events, where one statement after another is executed, with possible ramifications and repetitions. However, when you click a mouse button, for instance, while your program is being executed, you cannot be sure where your program is located at the time. In order to capture the clicks in the program we have to introduce a new programming concept called event control. The principle is as follows:

Define a function with any name, for example onMouseHit() that is never explicitly called in the program. Then ask that your computer calls this function whenever the mouse button is clicked. So, what you are telling the program is: Whenever the mouse button is clicked, execute onMouseHit().

PROGRAMMING CONCEPTS:
Event-driven programming, mouse event

 

 

MOUSE EVENTS

 

It is very easy to implement the new concept in Python. In the first event-driven program, the turtle should draw a fun figure in the main part. After this, you can decorate it by coloring certain areas with a mouse click.

Write the function onMouseHit(x, y), which delivers the x- and y-coordinate of the mouse click, and then give it a flood fill by using fill(x, y) (the filling of a closed region).

Most importantly you have to tell the system that it should call the function onMouseHit() whenever the mouse button is pressed. In order to do this you can use the parameter mouseHit when you call makeTurtle() and assign it the name of your function.

Use hideTurtle() so that the drawing is created faster.
 
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)      
Highlight program code (Ctrl+C copy, Ctrl+V paste)

 

 

MEMO

 

Technically, the concept of event-driven programming is implemented by writing a function to be called whenever the event occurs. You inform the system which function this is by passing the name of your function to makeTurtle(). Here you are using the notation parameter_name = parameter_value.
You can customize your preferences for the fill color with setFillColor().

You can write important information for the user in a status bar below the turtle window by using addStatusBar(n). The number n states the line height of the text bar (in pixels).

 

 

DRAWING WITH A MOUSE CLICK

 

The turtle should draw a star with rays at the position of the mouse click. For this you write the function onMouseHit(x, y) where you instruct the turtle how to draw the star. In order for onMouseHit() to be called when the mouse is clicked you pass the parameter name mouseHit in makeTurtle() the function name 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)
Highlight program code (Ctrl+C copy, Ctrl+V paste)

 

 

MEMO

 

The program has a flaw: If you click again while the turtle is still drawing a star, it will not finish that star but will immediately begin drawing the new star. However, it also continues to execute the commands of the old star, and so the new star is drawn incorrectly.

This wrong behavior is apparently due to the fact that every time you click, the function onMouseHit() it is called and executed, even if the previous execution is not done yet. In order to prevent this from happening, you can use the parameter named mouseHitX instead of mouseHit.

 

 

TURTLE CHASING THE MOUSE

 

Now you want the turtle to follow the mouse everywhere it goes. You cannot use the actual mouse click, but instead you should consider the movement of the mouse as an event. makeTurtle() knows the parameter mouseMoved to which you can pass a function that is called at every relocation of the mouse.

The function onMouseMoved(x, y) receives the current mouse coordinates x and y.

 
from gturtle import *

def onMouseMoved(x, y):
    setHeading(towards(x, y))
    forward(10)
      
makeTurtle(mouseMoved = onMouseMoved)
speed(-1)
Highlight program code (Ctrl+C copy, Ctrl+V paste)

 

 

MEMO

 

Besides mouseHit and mouseHitX there are other parameters of makeTurtle() at your disposal with which you can detect mouse events. Instead of x, y they use event, from which you can determine the coordinates of the mouse event.

mousePressed Mouse button is pressed
mouseReleased Mouse button is released
mouseClicked Mouse button is pressed and released
mouseDragged Mouse is moved while the button is pressed
mouseMoved Mouse is moved
mouseEntered Mouse enters the turtle window
mouseExited Mouse exits the turtle window

You can also use multiple parameters simultaneously, for example the two functions onMousePressed() and onMouseDragged():

makeTurtle(mousePressed = onMousePressed, mouseDragged = onMouseDragged)

You can find out which mouse button was pressed with isLeftMouseButton() or isRightMouseButton().

There is an important difference between these events and mouseHit: the movement of the turtle is not visible during the execution of the function. Therefore, you should either set the turtle on high speed with speed(-1), hide it with hideTurtle(), or execute the code for its movement in the main part of the program.

 

 

KEY EVENTS

 

Each time a keyboard key is hit, an event is "fired". To handle it, you register a callback function in makeTurtle by using the named parameter keyPressed. The callback receives an integer code that identifies the key you pressed. (You may find out the key codes by performing some simple tests.) In your program the turtles moves repeatedly 10 steps in forward direction. By hitting the cursor keys you can change its orientation in the four cardinal directions.  To prevent the turtle to leave the playground, the wrap mode is enabled.

 
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)
Highlight program code (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

EXERCISES


 
1.
Draw the adjacent star with a looping structure and fill it with mouse clicks so that it suits your taste.
 

2.
You can use the turtle to create a program where you can draw in freehand. To do this, lower the pen using the press event and move it using the drag event.  

3.
By pressing the left mouse button you draw any figure you would like. You can then color an area by clicking the right mouse button.  

4.

Write a program based on exercise 2 to draw a kaleidoscopical figure by dragging the mouse. When the  (hidden) turtle is moved, a line is drawn simultaneously in all 4 quadrants. To draw a line segment, you can define the following function:

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

 


5.

Modify the program with the keyboard control so that a closed area with the turtle inside is filled by typing the space key (key code 32). Use the program to create a filled letter.

   

 

 

 

EXTRA MATERIAL


 

YOUR PERSONAL MOUSE IMAGE

 

You are able to change the image of the mouse cursor to whatever you would like, thus giving your program a special look. To do this, use the command setCursor() and give it one of the values from the table below. You can even use your own image if you use setCustomCursor()and pass it the path to your image. A standard mouse icon is 32x32 pixels in size and has a transparent background. It should be saved in gif or png format. Both pencil.gif and cutemouse.gif are already available in the distribution of TigerJython in the folder sprites.

 

You can now decorate the tracking program shown above with cuteturtle or your own mouse figure. Make sure that the turtle always moves to the mouse by using moveTo().

from gturtle import *

def onMouseMoved(x, y):
      moveTo(x, y)
      
makeTurtle(mouseMoved = onMouseMoved)
setCustomCursor("sprites/cutemouse.gif")
speed(-1)
Highlight program code (Ctrl+C copy, Ctrl+V paste)

 

 

MEMO

 

By using speed(-1) you prevent the turtle from animating so that drawing with moveTo() gets faster.

Possible parameters of setCursor():

Parameter Icon
Cursor.DEFAULT_CURSOR Default icon
Cursor.CROSSHAIR_CURSOR Crosshair
Cursor.MOVE_CURSOR Moving cursor (cross arrows)
Cursor.TEXT_CURSOR Text cursor (vertical line)
Cursor.WAIT_CURSOR Waiting cursor

The sprites directory in the path indication of setCustomCursor() is in the same directory as your program [more... It can also be a subdirectory in the directory gamegrid in User Home.
You can also use a fully qualified file name, for example under Windows
d:/myturtles/mycursor.gif.
]