DEV Community

Kajiru
Kajiru

Posted on

Getting Started with 2D Games Using Tkinter (Part 3): Handling Mouse Events

Getting Started with 2D Games Using Tkinter (Part 3): Handling Mouse Events

In this article, we will learn about mouse events.

We will detect mouse movement and clicks, and retrieve their coordinates.


How to Set Up Mouse Events

Mouse events are bound to the Tk object as shown below.

  • <Button> detects mouse clicks
  • <Motion> detects mouse movement

The second argument specifies the function to be executed when the event occurs.

# main.py (excerpt)
root.bind("<Button>", on_mouse_clicked)  # Mouse click
root.bind("<Motion>", on_mouse_moved)    # Mouse movement
Enter fullscreen mode Exit fullscreen mode

1. Button Event

The on_mouse_clicked() function receives a Button event.

You can get:

  • the x-coordinate with e.x
  • the y-coordinate with e.y
# main.py (excerpt)
def on_mouse_clicked(e):
    print("Clicked:", e.x, e.y)
Enter fullscreen mode Exit fullscreen mode

Each time you click the mouse, the coordinates will be printed to the shell.


2. Motion Event

The on_mouse_moved() function handles mouse movement events.

It copies the mouse coordinates into the global variables mx and my.

(Don’t forget to declare them as global.)

# main.py (excerpt)
def on_mouse_moved(e):
    global mx, my
    mx, my = e.x, e.y  # Copy to global variables
Enter fullscreen mode Exit fullscreen mode

Drawing the Mouse Coordinates

In the update() function, the values stored in mx and my are drawn on the canvas.

The arguments of cvs.create_text() are:

  • x-coordinate
  • y-coordinate
  • text: the string to display
  • font: font name and size
  • tag: an identifier for the drawn object

Here, we use "hud" as the tag name.

# main.py (excerpt)
def update():
    """ Update function """
    cvs.delete("hud")  # Remove objects with the "hud" tag

    # Draw mouse coordinates
    msg = "x:{}, y:{}".format(mx, my)
    cvs.create_text(
        mx, my,
        text=msg,
        fill="white",
        font=FONT,
        tag="hud"
    )

    # Screen update
    root.after(30, update)
Enter fullscreen mode Exit fullscreen mode

About the tag

At the beginning of the update() function, this line is executed:

cvs.delete("hud")
Enter fullscreen mode Exit fullscreen mode

This removes all canvas objects with the "hud" tag.

In other words:

  1. Remove the previous coordinate text
  2. Redraw it at the current mouse position

This prevents old text from remaining on the screen.


When you run the program at this point, the mouse coordinates will be displayed at the cursor position.


Complete Code

Below is the complete code implementing mouse click and motion handling.

# main.py
import tkinter

# Canvas size
W, H = 480, 320

# Frame rate
F_RATE = 30  # Frames per second
F_INTERVAL = int(1000 / F_RATE)

# Font
FONT = ("Arial", 16)

# Mouse coordinates
mx, my = 0, 0

# Background image
bg_photo, bg_image = None, None

def init():
    """ Initialization function """
    global bg_photo, bg_image

    # Background
    bg_photo = tkinter.PhotoImage(file="images/bg_jigoku.png")
    bg_image = cvs.create_image(W / 2, H / 2, image=bg_photo)

def update():
    """ Update function """
    cvs.delete("hud")  # Remove HUD text

    # Draw mouse coordinates
    msg = "x:{}, y:{}".format(mx, my)
    cvs.create_text(
        mx, my,
        text=msg,
        fill="white",
        font=FONT,
        tag="hud"
    )

    # Screen update
    root.after(F_INTERVAL, update)

def on_mouse_clicked(e):
    print("Clicked:", e.x, e.y)

def on_mouse_moved(e):
    global mx, my
    mx, my = e.x, e.y

# Tkinter setup
root = tkinter.Tk()
root.title("Hello, Tkinter!!")
root.resizable(False, False)
root.bind("<Button>", on_mouse_clicked)
root.bind("<Motion>", on_mouse_moved)

# Canvas
cvs = tkinter.Canvas(width=W, height=H, bg="black")
cvs.pack()

init()
update()
root.mainloop()
Enter fullscreen mode Exit fullscreen mode

What’s Next?

Thank you for reading!

In the next article, we will create sprites and start drawing moving objects on the screen.

Stay tuned!

Top comments (0)