Skip to main content

Section 10.8 Events - Mouse and Keyboard

The SimpleGUI module has three interface widgets/controls that respond to user events:
  • buttons
  • text input boxes
  • the window frame (mouse/keyboard events)
As demonstrated in the default code on the main page of CodeSkulptor, the button event handler function, def click(), does not take any parameters. It is simply called when the button is clicked. The documentation shows that the text input event handler function, def input_handler(text_input), requires one parameter, which is how it receives the string of text the user enters.
Unlike buttons and text input boxes, which can only respond to one type of event, the window frame can recognize any of the following four types of events:
  • mouse click
  • mouse drag
  • key up
  • key down
The mouse events are triggered if the clicks or drags are on the canvas and the key events are recognized when the location of the mouse pointer is within the canvas area. This section shows examples of how to register and write these event handler functions.

Subsection 10.8.1 Mouse Events

Below is the documentation for mouse events:
This documentation shows us that in order to register a mouse click handler function, we need to access the set_mouseclick_handler() function on a frame object with the name, mouse_handler, being passed as an argument:
frame.set_mouseclick_handler(mouse_handler)
Notice that this event handler function, def mouse_handler(position), requires one parameter. You might be thinking that is weird because a mouse click happens in a two-dimensional window and so you need to specify an x and a y coordinate. But in SimpleGUI these coordinates are passed as a two-item tuple (remember tuples? the lists that can’t be modified?). So, if the mouse was clicked at 25 pixels to the right of the top-left corner and 100 pixels down from the top-left corner, the tuple (25,100) will be passed to the mouse click event handler.
Here is a code example:
The code above is similar to the examples we have seen already - a message is displayed on screen and can be changed if a user types a new message in the input box. But, it also draws a blue circle (outline only) on the canvas wherever the user last clicked. Note that there is one parameter in the mouse_click() function, called β€˜pos’ and we print this out to the output console, but also assign it to the global variable β€˜circ_pos’. That global variable is used in the draw() function to draw a circle.
Check your understanding

Checkpoint 10.8.1.

    Review and run the code example located below.
    Notice that when you click the mouse within the canvas, data is displayed within the mouse indicator box on the control panel.
    import simplegui
    import math
    
    WIDTH = 450
    HEIGHT = 300
    ball_pos = [WIDTH / 2, HEIGHT / 2]
    
    BALL_RADIUS = 15
    ball_color = "Red"
    
    def distance(pt1, pt2):
        return math.sqrt( (pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
    
    def click(pos):
        global ball_pos, ball_color
        if distance(pos, ball_pos) < BALL_RADIUS:
            ball_color = "Green"
        else:
            ball_pos = list(pos)
            ball_color = "Red"
    
    def draw(canvas):
        canvas.draw_circle(ball_pos, BALL_RADIUS, 1, "Black", ball_color)
    
    frame = simplegui.create_frame("Mouse selection", WIDTH, HEIGHT)
    frame.set_canvas_background("White")
    frame.set_mouseclick_handler(click)
    frame.set_draw_handler(draw)
    frame.start()
    
    What is the required parameter/argument for the mouse click event handler function?
  • a tuple with one x and one y coordinate
  • Correct!
  • x coordinate
  • Incorrect, a two-dimensional space requires two integers for a position.
  • y coordinate
  • Incorrect, two integer values are required.
  • a list of two integers
  • Incorrect, the values for the x,y coordinates are sent by the system as a tuple based on where the user clicks the mouse within the canvas.

Checkpoint 10.8.2.

    Evaluate this code example and add print(pos) as a statement within the def click() event handler function:
    import simplegui
    import math
    
    WIDTH = 450
    HEIGHT = 300
    ball_pos = [WIDTH / 2, HEIGHT / 2]
    
    BALL_RADIUS = 15
    ball_color = "Red"
    
    def distance(pt1, pt2):
        return math.sqrt( (pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
    
    def click(pos):
        global ball_pos, ball_color
        if distance(pos, ball_pos) < BALL_RADIUS:
            ball_color = "Green"
        else:
            ball_pos = list(pos)
            ball_color = "Red"
    
    def draw(canvas):
        canvas.draw_circle(ball_pos, BALL_RADIUS, 1, "Black", ball_color)
    
    frame = simplegui.create_frame("Mouse selection", WIDTH, HEIGHT)
    frame.set_canvas_background("White")
    frame.set_mouseclick_handler(click)
    frame.set_draw_handler(draw)
    frame.start()
    
    What occurs when you run this modified code and click the mouse within the canvas? Select all that apply.
  • a name error occurs: name ’pos’ is not defined.
  • Incorrect, after a mouse click, a tuple is passed as argument to the handler function and assigned to the default variable ’pos’.
  • one number is printed to the console.
  • Incorrect, a position in a two-dimensional space requires two integer values to specify the x,y coordinates.
  • two numbers print as a tuple to the console which match the numbers that appear within the mouse indicator box on the control panel.
  • Correct!
  • two numbers print as a tuple to the console which represent the x and y coordinates of the mouse click location within the canvas.
  • Correct!

Checkpoint 10.8.3.

    Review and run the following code:
    import simplegui
    
    WIDTH = 300
    HEIGHT = 300
    point = [WIDTH / 2, HEIGHT / 2]
    
    def draw(canvas):
        canvas.draw_circle(point, 20, 5, "White", "Red")
    
    def drag(pos):
        global point
        point = pos
    
    frame = simplegui.create_frame("Ball Drag", WIDTH, HEIGHT)
    frame.set_draw_handler(draw)
    frame.set_mousedrag_handler(drag)
    frame.start()
    
    Now remove the statement: global point
    What occurs when you run this modified code and drag the mouse within the canvas?
  • the circle is dragged across the canvas.
  • Incorrect, run the modified code to see what happens.
  • the circle remains stationary and the mouse pointer location continuously updates in the mouse indicator box.
  • Correct!
  • an error message prints to the console when trying to drag the mouse within the canvas.
  • Incorrect, the code still runs but not as intended.
  • an error message prints to the console after running the code but before dragging the mouse within the canvas.
  • Incorrect, however the removal of this global statement does lead to an error in the program.

Subsection 10.8.2 Keyboard Events

Let’s now look at how SimpleGUI handles keyboard events, because it is also different than the way the Turtle module handled keyboard events. Review the key event handler documentation which is located below:
We see here that there are two different key functions that can access the frame object:
  • frame.set_keydown_handler()
  • frame.set_keyup_handler()
For both of these you must specify the name of the function that will handle the event, and this event handler function, def key_handler(key), requires a single parameter to be passed which is the key that is pressed down (or released).
Click on the following link to review the key echo code example: https://py3.codeskulptor.org/#examples3_simplegui_key_echo.py. It is also pictured below with one extra print statement added on line 16. Add this print statement on line 16 in the keydown() handler function and run the code.

Note 10.8.4.

ASCII (American Standard Code for Information Interchange) is a standard way of using integer values to represent characters across many computer systems. For example, the letter ’A’ has the ASCII value of 65.
When you press down on a key, that key parameter is passed as an ASCII numeric value to the keydown() handler function. However, if you also want the letter to be displayed on the canvas, this ASCII numeric value needs to be converted to a character type using chr() and then stored in the global variable current_key. That variable, current_key, is then used in the draw() function to display the letter on the canvas.
When you lift your finger off that same key, the keyup() handler is called and the global variable is then reset to the space key, resulting in the letter disappearing from the canvas. The print statement (added on line 16) allows the numeric value of the key parameter (ASCII value) to be displayed in the console. Notice how these values change as you type different letters.
Check your understanding

Checkpoint 10.8.5.

    Review and make the following changes to the code below.
    Change current_key = chr(key) to current_key = key
    import simplegui
    
    current_key = ' '
          
    def keydown(key):
        global current_key
        current_key = chr(key)
    
    def draw(canvas):
        canvas.draw_text(current_key, [10, 25], 20, "Yellow")
    
    frame = simplegui.create_frame("Echo", 100, 100)
    frame.set_keydown_handler(keydown)
    frame.set_draw_handler(draw)
    frame.start()
    
    What occurs when you remove chr() and then click the mouse within the canvas?
  • an error message appears since the canvas.draw_text() function requires the first argument to be a string.
  • Correct! Note that char type variables are also recognized as string type variables in Python.
  • letters are displayed on the canvas when keys are pressed and the mouse pointer is within the canvas dimensions.
  • Incorrect, make the above change and run the code to find out what happens.
  • the program runs but letters do not appear on the canvas when keys are pressed.
  • Incorrect, run the code to find out the answer.
  • none of the above
  • Incorrect, one of the above choices is correct.
You have attempted of activities on this page.