PyQt5, как получить источник enterEvent?
В приложении, написанном на Python с использование PyQt5 есть кнопка.
someButton = QPushButton(objectName='button1')
На эту кнопку назначен ивент enterEvent, срабатывающий когда курсор наводится на эту кнопку
def some_func(event):
print('Some text')
someButton.enterEvent = some_func
Но что если таких кнопок несколько и я хочу получить информацию о том, какая кнопка послужила триггером ивента? Если бы это был сигнал вроде clicked, то я мог бы легко получить такое.
def some_func():
print(self.sender())
someButton.clicked.connect(some_func)
Но для enterEvent такое не работает, self.sender() возвращает None
Может виджет-триггер можно как-то получить из event, или же как-то иначе подключить enterEvent?
Желательно без переопределения кнопки в отдельный класс.
Ответы (2 шт):
В этом случае на помощь к вам придет lambda:
def func(event: QEnterEvent, sender: QPushButton):
print('Event:', event)
print('Sender:', sender.text())
if __name__ == "__main__":
app = QApplication([])
# ...
button = QPushButton("Button 1")
button.enterEvent = lambda e, btn=button: func(e, sender=btn) # Можно и без sender=, но для наглядности
button.show()
button = QPushButton("Button 2")
button.enterEvent = lambda e, btn=button: func(e, sender=btn)
button.show()
button = QPushButton("Button 3")
button.enterEvent = lambda e, btn=button: func(e, sender=btn)
button.show()
button = QPushButton("Button 4")
button.enterEvent = lambda e, btn=button: func(e, sender=btn)
button.show()
sys.exit(app.exec_())
У вас есть два варианта.
Согласно документации:
[virtual protected] void QWidget::enterEvent(QEvent *event)
Этот обработчик событий может быть повторно реализован в подклассе для приема событий вxода в виджет, которые передаются в параметре события. Событие отправляется виджету, когда курсор мыши входит в виджет.
from PyQt5.Qt import *
class Button(QPushButton):
def __init__(self, num):
super().__init__()
self.setText(f"Кнопка {num}")
self.setObjectName(f"button{num}")
def leaveEvent(self, event):
print(f'leaveEvent: {self.text()}')
def enterEvent(self, event):
print(f'enterEvent: {self.text()}')
class MainWindow(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
for i in range(5):
btn = Button(i+1)
layout.addWidget(btn)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Другой вариант, который используется в практике - это установка фильтра событий.
void QObject::installEventFilter(QObject *filterObj)
Устанавливает фильтр событий filterObj на этот объект.
from PyQt5.Qt import *
class MainWindow(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout(self)
for i in range(5):
btn = QPushButton(f"Кнопка {i+1}", objectName=f"button{i+1}")
btn.installEventFilter(self)
layout.addWidget(btn)
def eventFilter(self, obj, event):
if event.type() == QEvent.Leave:
print(f'QEvent.Leave: obj={obj.text()}, {obj.objectName()}')
return True
elif event.type() == QEvent.Enter:
print(f'\nQEvent.Enter: obj={obj.text()}, {obj.objectName()}')
return True
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

