Search code examples
pythonpyqt5qframe

Trigger a function on clicking QFrame


I am working on a project with PyQt5 which has QFrames. I am using mouse press event to trigger a function on clicking frame as below :

frame.mousePressEvent = lambda x: print_name(x, name)

Above line is not executed at the start, It is executed after user has done some work in UI.

I am getting the behaviour I want but here is the problem:

If the user clicks the frame after the above line of code is executed, it works fine but if the user clicks on the frame before the above line of the code is executed and later again clicks the frame (after code is executed), I am not getting the same behaviour. Basically nothing happens.

I want to know where is the problem and how do I solve it?


Solution

  • The problem is caused because PyQt5 caches the methods so if the method is assigned then it cannot be changed. Instead of following the bad practice of assigning methods to mousePressEvent there are other better alternatives such as:

    1. Implement inheritance

      class Frame(QFrame):
          def mousePressEvent(self, event):
              super().mousePressEvent(event)
              print(event)
      
    2. Use an event filter

      class MouseObserver(QObject):
          def __init__(self, widget):
              super().__init__(widget)
              self._widget = widget
              self.widget.installEventFilter(self)
      
          @property
          def widget(self):
              return self._widget
      
          def eventFilter(self, obj, event):
              if obj is self.widget and event.type() == QEvent.MouseButtonPress:
                  print(event)
              return super().eventFilter(obj, event)
      

      Then

      observer = MouseObserver(frame)
      

    The second seems the most appropriate for your case.