Pygame event handlers interfering with one another?

Question:

I’m making a game launcher in Python 3.7, and I’m using the Pygame (“pg”) library. I made a class for clickable text (“links”), and I have an event handler which checks for the pg.QUIT function.

I have a while loop set up that begins with the event handler function that checks for pg.QUIT, and later on in the loop, I have a class function that listens to see if the link has been clicked.

Unfortunately, when they are both able to run within the loop, they interfere with each other and some input gets ignored, such as pg.MOUSEBUTTONDOWN (which is crucial here).

I’ve tried disabling the event handler (I just commented the line that calls it), and that made it work; every input was registered. However, I don’t want to check for pg.QUIT inside of an object class, and I don’t want to look for specific objects in my event handler: I want to keep these things separate.

The code in my class is as follows:

(Inside TextObject class)

def link():

    for e in pg.event.get():

        if e.type == pg.MOUSEBUTTONDOWN and {mouse is over link}:

            print('click!')

The code in my event handler is as follows:

def handle():

    for e in pg.event.get():

        if e.type == pg.QUIT:

            running = False

The code in my while loop is as follows:

while running:

    handle()

    {update screen and draw text}

    textObject.link()

    clock.tick(fps)

I want the program to listen for pg.QUIT, and then if that hasn’t happened, move on and listen to see if the link has been clicked.

When I run it, the program only prints ‘click!’ after I’ve clicked the link about twenty times. It seems almost random.

I’m predicting that the two functions are interfering with each other, and I could fix it with some kind of joint function, but I’d really prefer to keep these functions vague without hard-coding in some text coordinates, y’know?

Thanks.

P.S. I used pseudo-code to give some context, but I’ve already confirmed that the issue lies in the code I’ve written explicitly.

Asked By: Endvisible

||

Answers:

Move all the event handling into your main loop. You’re losing events because some are being handled in one loop (and discarding the un-handled events), and similarly in the other event loop, but for other event types.

Spreading the event processing throughout various parts of the code makes the logic and debugging harder. Ideally it works well to have a single logical item handled in a single place. So when you have an issue with user-input, you only need to debug the user-input section – rather than this-function, that-function, and this-thing-in-a-file-over-there.

Sure, if you need to see which button was pressed or whatever, write a function to do that, then call the function (passing it the mouse position) during the click event handling.

while running:
    # Handle user input
    for e in pg.event.get():

        if e.type == pg.QUIT:
            running = False

        elif e.type == pg.MOUSEBUTTONDOWN:
            if {mouse is over link}:
                print('click!')

     # Handle screen painting
         ...
Answered By: Kingsley

Although I consider Kingsley answer as really good and valuable, I find splitting event execution onto separate files/functions useful in some cases (as sort of categorisation making code cleaner – especially if this goes with clean visualisation, like in this workspace of mine where use of events is seen easily by additional variable and restricted to few functions).

My way of doing that is by putting events into variable, so those are called once, and referring them further:

while running:

    events = pg.event.get() # "variablised" event, so we call it once per frame
    for e in events: # stuff can be used explicitly

        if e.type == pg.QUIT:

            running = False

    textObject.link(events) #or passed to another function

This is how another file/function will look then:

(Inside TextObject class)

def link(events):

    for e in events:

        if e.type == pg.MOUSEBUTTONDOWN and {mouse is over link}:

            print('click!')

I wanted to revive this topic because it gave me idea how to solve the problem the way I portrayed, yet I disagreed (only to some extent) with Kingsley’s answer which can be really messy in some cases.

Answered By: Toma400
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.