Since many times it is asked how to detect the events that affect a widget then in this answer I will detail the solution and it will be used as a canonical answer for future questions.
To detect an event from a widget there are several solutions:
- Override a method
If the widget has a method that handles that event then an option is to override that method and associate it with a signal so that other objects can be notified.
In the particular case of the mouse release event, this is handled by the mouseReleaseEvent method.
from PyQt5 import QtCore, QtWidgets
class TextEdit(QtWidgets.QTextEdit):
released = QtCore.pyqtSignal()
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
self.released.emit()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.textedit = TextEdit()
self.textedit.released.connect(self.handle_released)
self.setCentralWidget(self.textedit)
@QtCore.pyqtSlot()
def handle_released(self):
print("released")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
- Use an event filter
Qt allows you to monitor the events using an event filter, so you can take advantage of this feature to emit a signal in a similar way to the previous solution.
In the case of classes that inherit from QAbstractScrollArea, the mouse methods are transmitted to the viewport, so that object must be monitored.
from PyQt5 import QtCore, QtWidgets
class ReleaseFilter(QtCore.QObject):
released = QtCore.pyqtSignal()
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() == QtCore.QEvent.MouseButtonRelease:
self.released.emit()
return super().eventFilter(obj, event)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.textedit = QtWidgets.QTextEdit()
rf = ReleaseFilter(self.textedit.viewport())
rf.released.connect(self.handle_released)
self.setCentralWidget(self.textedit)
@QtCore.pyqtSlot()
def handle_released(self):
print("released")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())