Designing a Button UI Module for Pygame

  • Enter – When a MOUSEMOTION event has told the button that the mouse is over the button when previously it wasn’t.
  • Exit – When a MOUSEMOTION event has told the button that the mouse is no longer over the button when previously it was.
  • Move – When the button has received a MOUSEMOTION event.
  • Down – When the mouse is pressed down on the button.
  • Up – When the mouse is released on the button.
  • Click – When the mouse was pressed down on the button and released over the button. (Releasing the mouse off of the button does not trigger the click event.)

(Note: The buttons won’t produce Pygame USEREVENTS. I didn’t see a significant need for them.)

As to how the mouse button looks, I’ll be using the Windows look-and-feel of buttons. Here’s what they look like zoomed in:

Notice that the 3D appearance is caused by drawing these black, gray, and white outlines. These lines don’t change if the background color of the button changes.

What the API will Look Like

Before diving into coding, we need a concrete plan for how other programmers will use this module. It doesn’t matter how sophisticated your library is, if it is opaque, difficult to learn, and inconsistent no one will want to learn it and it will not be used. It’s important to get these details right the first time, because making changes (like changing a function name or getting rid of a class) later on could break other people’s code that uses your library. This means they won’t adopt newer versions and new features (since the newer version breaks their code), which further limits the popularity of your module.

The button’s API will have three main parts: the constructor function that creates it, the function that draws the button to a pygame.Surface object (to display it on the screen), and a handleEvent() method that we can pass pygame.Event objects to so it knows what is happening in the program. The code will roughly look like this:

myButton = pygbutton.PygButton(rectObj, 'Caption text') ... for event in pygame.event.get(): # event handling loop myButton.handleEvent(event) ... myButton.draw(displaySurface)

Before we start coding, we should write out the method names and parameters for the PygButton class first. This will help cement what we want to code before we start coding:

  • def __init__(self, rect=None, caption='', bgcolor=LIGHTGRAY, fgcolor=BLACK, font=None, normal=None, down=None, highlight=None) – The constructor. Note that pretty much everything has a default argument. If the user just wants asimple button, we shouldn’t have to make her write out tons of boilerplate code. Let’s just supply default values.
  • def handleEvent(self, eventObj) – Changes the button’s state if the Pygame event passed is relevant.
  • def draw(self, surfaceObj) – Draws the button (in its current state) to the surfaceObj surface.
  • def mouseClick(self, event) – Called when the button has a click event. (These methods don’t do anything in the PygButton class, but you can override this class to implement code in these methods.)
  • def mouseEnter(self, event) – Called when the button has a “mouse enter” event.
  • def mouseExit(self, event) – Called when the button has a “mouse exit” event.
  • def mouseMove(self, event) – Called when the button has a “mouse move” event.
  • def mouseDown(self, event) – Called when the button has a mouse button down event.
  • def mouseUp(self, event) – Called when the button has a mouse button up event.
  • def setSurfaces(self, normalSurface, downSurface=None, highlightSurface=None) – Let’s the user specify either image filenames or pygame.Surface objects to use for each of the states. (This sets the button to be an image-based button.)

And here are some properties that we’d like to set for the PygButton class. Whenever you think you’ll need a get and set method for something (i.e. getCaption() and setCaption() instead of just a caption property), this is a strong indication that a property would be better instead.

Page 2 of 6 | Previous page | Next page