Eсть ли аналог enterEvent и leaveEvent в pyqt5?

Я хочу использовать enterEvent и leaveEvent но для их использования нужно создавать новый объект и это неудобно. Я хочу использовать конструкцию

self.clicked.connect(self.fun)

но со свойствами enterEvent или leaveEvent

Есть ли аналоги?

Что мне приходится делать

class Widget1(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget1, self).__init__(parent)
    def leaveEvent(self, event):
        print('1')
    def enterEvent(self, event):
        print('2')


class Widget2(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget1, self).__init__(parent)
    def leaveEvent(self, event):
        print('1')
    def enterEvent(self, event):
        print('2')



class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        wid1 = Widget1(self)
        wid2 = Widget2(self)

Что бы я хотел сделать

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        
        wid1 = QtWidgets.QWidget(self)
        wid2 = QtWidgets.QWidget(self)
        
        wid1.???.connect(self.fun)
        wid1.???.connect(self.fun2)
        wid2.???.connect(self.fun2)
        wid2.???.connect(self.fun)
        
        
    def fun(self, event):
        print('1')
    def fun2(self, event):
        print('2')

Ответы (1 шт):

Автор решения: S. Nick

Согласно документации:

[virtual protected] void QWidget::enterEvent(QEvent *event)

Этот обработчик событий может быть повторно реализован в подклассе для приема событий вxода в виджет, которые передаются в параметре события. Событие отправляется виджету, когда курсор мыши входит в виджет.

[virtual protected]void QWidget::leaveEvent(QEvent *event)

Этот обработчик событий может быть повторно реализован в подклассе для получения событий выхода из виджета, которые передаются в параметре события. Событие выхода отправляется виджету, когда курсор мыши покидает виджет.

Это первый вариант:

from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.Qt import *


class Widget1(QtWidgets.QLabel):    # QWidget
    def __init__(self, parent=None):
        super(Widget1, self).__init__(parent)
        self.setText("Widget1")
        self.setStyleSheet("background-color: #f00;")
        
    def leaveEvent(self, event):
        print('class Widget1: leaveEvent')
        
    def enterEvent(self, event):
        print('class Widget1: enterEvent')


class Widget2(QtWidgets.QLabel):
    def __init__(self, parent=None):
        super(Widget2, self).__init__(parent)
        self.setText("Widget2")
        self.setStyleSheet("background-color: #00f;")
        
    def leaveEvent(self, event):
        print('class Widget2: leaveEvent')
            
    def enterEvent(self, event):
        print('class Widget2: enterEvent')


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        
        wid1 = Widget1(self)
        wid2 = Widget2(self)
        
        layout = QVBoxLayout(self)
        layout.addWidget(wid1)           # , alignment=Qt.AlignCenter
        layout.addWidget(wid2)
        
        
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Widget()
    window.resize(300,300)
    window.show()
    sys.exit(app.exec_())

Другой вариант, который используется в практике - это установка фильтра событий.

void QObject::installEventFilter(QObject *filterObj)

Устанавливает фильтр событий filterObj на этот объект.

Например: monitoredObj->installEventFilter(filterObj);

Фильтр событий - это объект, который получает все события, отправленные этому объекту. Фильтр может остановить событие или перенаправить его этому объекту. Фильтр событий filterObj получает события через свою функцию eventFilter(). Функция eventFilter() должна возвращать True, если событие должно быть отфильтровано (т.е. остановлено); в противном случае он должен вернуть False.

[virtual]bool QObject::eventFilter(QObject *watched, QEvent *event)

Фильтрует события, если этот объект был установлен как фильтр событий для наблюдаемого объекта. При повторной реализации этой функции, если вы хотите отфильтровать событие, то есть остановить его дальнейшую обработку, верните True; в противном случае верните False.

from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.Qt import *


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.setObjectName('widget')
        
        self.wid1 = QLabel(objectName='widget_1', styleSheet="background-color: #f00;")
        self.wid1.setText("Widget1")
        self.wid2 = QLabel(objectName='widget_2', styleSheet="background-color: #00f;")
        self.wid2.setText("Widget2")
        
        self.wid1.installEventFilter(self)
        self.wid2.installEventFilter(self)
        
        layout = QVBoxLayout(self)
        layout.addWidget(self.wid1)       
        layout.addWidget(self.wid2)
        
    def fun(self, widget, event):
        print(f'{widget} -> {event}\n')
        
    def fun2(self, widget, event):
        print(f'{widget} -> {event}\n')

    def eventFilter(self, obj, event):
        if obj is self.wid1 and event.type() == QEvent.Leave:
            self.fun(self.wid1.objectName(), 'QEvent.Leave')
            return True
        elif obj is self.wid1 and event.type() == QEvent.Enter:
            self.fun2(self.wid1.objectName(), 'QEvent.Enter')
            return True
        elif obj is self.wid2 and event.type() == QEvent.Leave:
            self.fun(self.wid2.objectName(), 'QEvent.Leave')
            return True
        elif obj is self.wid2 and event.type() == QEvent.Enter:
            self.fun2(self.wid2.objectName(), 'QEvent.Enter')            
            return True
            
        return super().eventFilter(obj, event)
    
        
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Widget()
    window.resize(300,300)
    window.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка