如何接收子部件的悬停事件?

How to receive hover events for child widgets?

我有一个 QWidget 包含另一个(子)小部件,我想为其处理 hoverEnterEventhoverLeaveEventThe documentation 提到

Mouse events occur when a mouse cursor is moved into, out of, or within a widget, and if the widget has the Qt::WA_Hover attribute.

所以我尝试通过设置此属性并实现相应的事件处理程序来接收悬停事件:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout

class TestWidget(QWidget):
    def __init__(self):
        super().__init__()
        layout = QVBoxLayout()
        layout.addWidget(TestLabel('Test 1'))
        layout.addWidget(TestLabel('Test 2'))
        self.setLayout(layout)
        self.setAttribute(Qt.WA_Hover)

class TestLabel(QLabel):
    def __init__(self, text):
        super().__init__(text)
        self.setAttribute(Qt.WA_Hover)

    def hoverEnterEvent(self, event):  # this is never invoked
        print(f'{self.text()} hover enter')

    def hoverLeaveEvent(self, event):  # this is never invoked
        print(f'{self.text()} hover leave')

    def mousePressEvent(self, event):
        print(f'{self.text()} mouse press')

app = QApplication([])
window = TestWidget()
window.show()
sys.exit(app.exec_())

然而它似乎不起作用,没有收到悬停事件。另一方面,mousePressEvent 确实有效。

此外,我还尝试了以下操作:

如何在我的自定义 QWidget 上接收悬停事件?

QWidget like the QLabel do not have the hoverEnterEvent and hoverLeaveEvent methods, those methods are from the QGraphicsItem 所以你的代码不起作用。

如果你想监听类型的悬停事件你必须覆盖event()方法:

import sys
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout


class TestWidget(QWidget):
    def __init__(self):
        super().__init__()
        layout = QVBoxLayout(self)
        layout.addWidget(TestLabel("Test 1"))
        layout.addWidget(TestLabel("Test 2"))


class TestLabel(QLabel):
    def __init__(self, text):
        super().__init__(text)
        self.setAttribute(Qt.WA_Hover)

    def event(self, event):
        if event.type() == QEvent.HoverEnter:
            print("enter")
        elif event.type() == QEvent.HoverLeave:
            print("leave")
        return super().event(event)


def main():
    app = QApplication(sys.argv)
    window = TestWidget()
    window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

您知道您可以使用 QWidget 的 enterEvent 和 leaveEvent 来做到这一点吗?您需要做的就是更改方法名称。您甚至不需要在标签上设置悬停属性。

from PyQt5.QtWidgets import QApplication, QGridLayout, QLabel, QWidget


class Window(QWidget):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        layout = QGridLayout()
        self.label = MyLabel(self)
        layout.addWidget(self.label)
        self.setLayout(layout)
        text = "hover label"
        self.label.setText(text)


class MyLabel(QLabel):
    def __init__(self, parent=None):
        super(MyLabel, self).__init__(parent)
        self.setParent(parent)

    def enterEvent(self, event):
        self.prev_text = self.text()
        self.setText('hovering')

    def leaveEvent(self, event):
        self.setText(self.prev_text)


if __name__ == "__main__":
    app = QApplication([])
    w = Window()
    w.show()
    app.exit(app.exec_())