returning an IF statment without closing a loop event filter pyqt5

Question:

I have a number of frames that are made depending on the number of items in a list. I want to click on this frame to expand it to have more options. I have installed an event filter on the frame. I have been making the frames like this:

        for num, i in enumerate(self.data):

            exec(f"self.frame_user_{num} = QFrame(self.frame_user_frame)")                 
            getattr(self, f"frame_user_{num}").setMouseTracking(True)
            getattr(self, f"frame_user_{num}").installEventFilter(self)

and it works fine.

when it comes to the event filter

    def eventFilter(self, object, event):
        loop_length = len(self.data)
        z = 0
        if event.type() == QEvent.MouseButtonPress:
            while z < loop_length:
                if object == getattr(self, f"frame_user_{z}"):
                    self.expand_buttons(z)
                else:
                    return False
                z += 1
        else:
            return False

The problem I have is I need to close the if statement in the loop with an else: return False otherwise I get the error:

a ‘bool’ is expected not ‘NoneType’

but if I put the else: return false it ends the loop and doesn’t go through the rest of the frames.

How would I write the event filter so It goes through each frame without closing the loop and not giving an error?

or is there another better way?

Asked By: Ben

||

Answers:

If you get to the end of the while loop without executing else: return False, you’ll exit the function without an explicit return statement. Put another return after the loop.

def eventFilter(self, object, event):
    loop_length = len(self.data)
    if event.type() == QEvent.MouseButtonPress:
        for z in range(loop_length):
            if object == getattr(self, f"frame_user_{z}"):
                self.expand_buttons(z)
            else:
                return False
        return True
    else:
        return False

I return True there since all the other paths return False, so I assume this is considered the successful case.

However, I’m not sure that your loop is doing what you really want. It will return False immediately if object is not the same as self.frame_user_0, so you won’t keep searching for other matching attributes. I suspect what you want is:

for z in range(loop_length):
    if object == getattr(self, f"frame_user_{z}"):
        self.expand_buttons(z)
        return True
return False

This will look for the first frame_user_{z} attribute that matches object, expand it, and return True. If none are found, it will return False.

Answered By: Barmar
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.