如何接收子部件的悬停事件?
How to receive hover events for child widgets?
我有一个 QWidget
包含另一个(子)小部件,我想为其处理 hoverEnterEvent
和 hoverLeaveEvent
。 The 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
确实有效。
此外,我还尝试了以下操作:
- 为所有小部件设置
self.setMouseTracking(True)
,
- 将
TestWidget
包裹在 QMainWindow
中(虽然这不是我想要为实际应用程序做的),
- 在父部件和
event.accept()
上实现事件处理程序(尽管据我了解,事件从内向外传播,因此不需要这样做)。
如何在我的自定义 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_())
我有一个 QWidget
包含另一个(子)小部件,我想为其处理 hoverEnterEvent
和 hoverLeaveEvent
。 The 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
确实有效。
此外,我还尝试了以下操作:
- 为所有小部件设置
self.setMouseTracking(True)
, - 将
TestWidget
包裹在QMainWindow
中(虽然这不是我想要为实际应用程序做的), - 在父部件和
event.accept()
上实现事件处理程序(尽管据我了解,事件从内向外传播,因此不需要这样做)。
如何在我的自定义 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_())