PyQt6 不调用任何悬停在框架上的事件
PyQt6 Isn't calling any events for hovering over a frame
我的目标是检测用户何时悬停或停止悬停在帧上,但每当我尝试使用 eventFilter 检测时,都没有事件 运行 表明这一点。 hoverEnter、hoverLeave 和 hoverMouseMove 的事件 ID 是 127、128 和 129,但是如果您 运行 代码,您会发现它们根本就没有出现。这是失败的代码:
import sys
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout()
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = QFrame()
self.frame.setStyleSheet("background-color: lightblue;")
self.innerLayout = QHBoxLayout(self.frame)
self.label = QLabel(self.frame)
self.label.setText("Example Frame")
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.setLayout(self.outerLayout)
def eventFilter(self, obj, event):
if event.type() == 127:
print("hovered")
elif event.type() == 128:
print("no longer hovered")
elif event.type() == 129:
print("hover move event")
print(event.type())
return True
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.installEventFilter(window)
window.show()
sys.exit(app.exec())
我的最终目标是能够检测 QFrame 何时被点击。我在想我会尝试通过检查鼠标点击来做到这一点,如果鼠标悬停在框架上,则触发该功能。
首先需要注意的是clicked不是一个事件而是一个信号。当按钮接收到 MouseButtonRelease 事件时,将发出按钮单击信号。
在这个答案中,我将至少展示以下方法来实现 QFrame 中的点击信号。
覆盖 mouseReleaseEvent
import sys
from PyQt6.QtCore import pyqtSignal, pyqtSlot
from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget
class Frame(QFrame):
clicked = pyqtSignal()
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
self.clicked.emit()
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout(self)
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = Frame()
self.frame.setStyleSheet("background-color: lightblue;")
self.label = QLabel(text="Example Frame")
self.innerLayout = QHBoxLayout(self.frame)
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.frame.clicked.connect(self.handle_clicked)
@pyqtSlot()
def handle_clicked(self):
print("frame clicked")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.show()
sys.exit(app.exec())
使用事件过滤器:
import sys
from PyQt6.QtCore import QEvent
from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout(self)
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = QFrame()
self.frame.setStyleSheet("background-color: lightblue;")
self.label = QLabel(text="Example Frame")
self.innerLayout = QHBoxLayout(self.frame)
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.frame.installEventFilter(self)
# for move mouse
# self.frame.setMouseTracking(True)
def eventFilter(self, obj, event):
if obj is self.frame:
if event.type() == QEvent.Type.MouseButtonPress:
print("press")
# for move mouse
# elif event.type() == QEvent.Type.MouseMove:
# print("move")
elif event.type() == QEvent.Type.MouseButtonRelease:
print("released")
return super().eventFilter(obj, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.show()
sys.exit(app.exec())
加上
O 尝试的很大一部分错误是,通过执行 window.installEventFilter(window)
它只监听来自 window 本身而不是来自 QFrame 的事件。解决方案是将 QFrame 事件发送到 class window.frame.installEventFilter(window)
.
另一方面,不要使用数字代码,而是使用枚举,因为它们更具可读性。
另一方面,对于鼠标事件,必须启用 Qt::WA_Hover
属性(阅读 docs 了解更多信息)
import sys
from PyQt6.QtCore import QEvent, Qt
from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout(self)
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = QFrame()
self.frame.setStyleSheet("background-color: lightblue;")
self.label = QLabel(text="Example Frame")
self.innerLayout = QHBoxLayout(self.frame)
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.frame.setAttribute(Qt.WidgetAttribute.WA_Hover)
self.frame.installEventFilter(self)
def eventFilter(self, obj, event):
if obj is self.frame:
if event.type() == QEvent.Type.HoverEnter:
print("enter")
elif event.type() == QEvent.Type.HoverMove:
print("move")
elif event.type() == QEvent.Type.HoverLeave:
print("leave")
return super().eventFilter(obj, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.show()
sys.exit(app.exec())
我的目标是检测用户何时悬停或停止悬停在帧上,但每当我尝试使用 eventFilter 检测时,都没有事件 运行 表明这一点。 hoverEnter、hoverLeave 和 hoverMouseMove 的事件 ID 是 127、128 和 129,但是如果您 运行 代码,您会发现它们根本就没有出现。这是失败的代码:
import sys
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout()
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = QFrame()
self.frame.setStyleSheet("background-color: lightblue;")
self.innerLayout = QHBoxLayout(self.frame)
self.label = QLabel(self.frame)
self.label.setText("Example Frame")
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.setLayout(self.outerLayout)
def eventFilter(self, obj, event):
if event.type() == 127:
print("hovered")
elif event.type() == 128:
print("no longer hovered")
elif event.type() == 129:
print("hover move event")
print(event.type())
return True
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.installEventFilter(window)
window.show()
sys.exit(app.exec())
我的最终目标是能够检测 QFrame 何时被点击。我在想我会尝试通过检查鼠标点击来做到这一点,如果鼠标悬停在框架上,则触发该功能。
首先需要注意的是clicked不是一个事件而是一个信号。当按钮接收到 MouseButtonRelease 事件时,将发出按钮单击信号。
在这个答案中,我将至少展示以下方法来实现 QFrame 中的点击信号。
覆盖 mouseReleaseEvent
import sys from PyQt6.QtCore import pyqtSignal, pyqtSlot from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget class Frame(QFrame): clicked = pyqtSignal() def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) self.clicked.emit() class MainApp(QWidget): def __init__(self): super().__init__() self.setWindowTitle("Test Window") self.resize(300, 200) self.outerLayout = QHBoxLayout(self) self.outerLayout.setContentsMargins(50, 50, 50, 50) self.frame = Frame() self.frame.setStyleSheet("background-color: lightblue;") self.label = QLabel(text="Example Frame") self.innerLayout = QHBoxLayout(self.frame) self.innerLayout.addWidget(self.label) self.outerLayout.addWidget(self.frame) self.frame.clicked.connect(self.handle_clicked) @pyqtSlot() def handle_clicked(self): print("frame clicked") if __name__ == "__main__": app = QApplication(sys.argv) window = MainApp() window.show() sys.exit(app.exec())
使用事件过滤器:
import sys from PyQt6.QtCore import QEvent from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget class MainApp(QWidget): def __init__(self): super().__init__() self.setWindowTitle("Test Window") self.resize(300, 200) self.outerLayout = QHBoxLayout(self) self.outerLayout.setContentsMargins(50, 50, 50, 50) self.frame = QFrame() self.frame.setStyleSheet("background-color: lightblue;") self.label = QLabel(text="Example Frame") self.innerLayout = QHBoxLayout(self.frame) self.innerLayout.addWidget(self.label) self.outerLayout.addWidget(self.frame) self.frame.installEventFilter(self) # for move mouse # self.frame.setMouseTracking(True) def eventFilter(self, obj, event): if obj is self.frame: if event.type() == QEvent.Type.MouseButtonPress: print("press") # for move mouse # elif event.type() == QEvent.Type.MouseMove: # print("move") elif event.type() == QEvent.Type.MouseButtonRelease: print("released") return super().eventFilter(obj, event) if __name__ == "__main__": app = QApplication(sys.argv) window = MainApp() window.show() sys.exit(app.exec())
加上
O 尝试的很大一部分错误是,通过执行 window.installEventFilter(window)
它只监听来自 window 本身而不是来自 QFrame 的事件。解决方案是将 QFrame 事件发送到 class window.frame.installEventFilter(window)
.
另一方面,不要使用数字代码,而是使用枚举,因为它们更具可读性。
另一方面,对于鼠标事件,必须启用 Qt::WA_Hover
属性(阅读 docs 了解更多信息)
import sys
from PyQt6.QtCore import QEvent, Qt
from PyQt6.QtWidgets import QApplication, QFrame, QHBoxLayout, QLabel, QWidget
class MainApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Test Window")
self.resize(300, 200)
self.outerLayout = QHBoxLayout(self)
self.outerLayout.setContentsMargins(50, 50, 50, 50)
self.frame = QFrame()
self.frame.setStyleSheet("background-color: lightblue;")
self.label = QLabel(text="Example Frame")
self.innerLayout = QHBoxLayout(self.frame)
self.innerLayout.addWidget(self.label)
self.outerLayout.addWidget(self.frame)
self.frame.setAttribute(Qt.WidgetAttribute.WA_Hover)
self.frame.installEventFilter(self)
def eventFilter(self, obj, event):
if obj is self.frame:
if event.type() == QEvent.Type.HoverEnter:
print("enter")
elif event.type() == QEvent.Type.HoverMove:
print("move")
elif event.type() == QEvent.Type.HoverLeave:
print("leave")
return super().eventFilter(obj, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainApp()
window.show()
sys.exit(app.exec())