You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PySide6中实现QGroupBox的鼠标悬停检测与逻辑执行

PySide6实现QGroupBox鼠标悬停检测

Qt的QGroupBox没有直接提供鼠标悬停/离开的信号,我们可以通过两种常用方式实现需求:

方法一:使用事件过滤器(无需子类化)

直接给目标QGroupBox安装事件过滤器,拦截鼠标进入和离开事件:

import sys
from PySide6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QGroupBox
)
from PySide6.QtCore import QEvent

class EmailBox(QWidget):
    def __init__(self) -> None:
        super().__init__()
        self._emailbox_layout = QVBoxLayout()
        self.setLayout(self._emailbox_layout)
        self._emailbox_layout.addWidget(self._Draw())

    def _Draw(self):
        self._gb = QGroupBox("邮件组框")
        # 给组框安装事件过滤器
        self._gb.installEventFilter(self)
        # 给组框设置布局(修正原代码布局逻辑问题)
        layout = QVBoxLayout(self._gb)
        return self._gb

    def _hovered(self):
        print("鼠标悬停在组框上")
        # 此处可添加UI逻辑,比如添加按钮:
        # from PySide6.QtWidgets import QPushButton
        # btn = QPushButton("操作按钮")
        # self._gb.layout().addWidget(btn)

    def _not_hovered(self):
        print("鼠标离开组框")
        # 此处可移除UI元素,比如清理按钮:
        # while self._gb.layout().count():
        #     child = self._gb.layout().takeAt(0)
        #     if child.widget():
        #         child.widget().deleteLater()

    def eventFilter(self, watched, event):
        # 仅处理目标QGroupBox的事件
        if watched == self._gb:
            if event.type() == QEvent.Enter:
                self._hovered()
            elif event.type() == QEvent.Leave:
                self._not_hovered()
        # 返回父类处理结果,不影响其他事件流程
        return super().eventFilter(watched, event)

def main():
    app: QApplication = QApplication(sys.argv)
    ex = EmailBox()
    ex.resize(400, 300)
    ex.show()
    sys.exit(app.exec())

if __name__ == "__main__":
    main()

关键说明:

  • installEventFilter(self):将当前EmailBox实例设为QGroupBox的事件过滤器,所有发往组框的事件都会先经过eventFilter方法处理。
  • eventFilter方法:判断事件类型,QEvent.Enter对应鼠标进入控件区域,QEvent.Leave对应鼠标离开,分别调用对应的处理函数。
  • 修正了原代码布局错误:原代码将QGroupBox加到新GridLayout但未绑定到控件,此处改为直接给QGroupBox设置布局。

方法二:子类化QGroupBox(自定义信号)

如果需要在多个地方复用带悬停检测的组框,可子类化QGroupBox并定义自定义信号:

import sys
from PySide6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QGroupBox
)
from PySide6.QtCore import QEvent, Signal

class HoverGroupBox(QGroupBox):
    # 自定义悬停和离开信号
    mouse_hovered = Signal()
    mouse_left = Signal()

    def __init__(self, title="", parent=None):
        super().__init__(title, parent)

    def enterEvent(self, event):
        self.mouse_hovered.emit()
        super().enterEvent(event)

    def leaveEvent(self, event):
        self.mouse_left.emit()
        super().leaveEvent(event)

class EmailBox(QWidget):
    def __init__(self) -> None:
        super().__init__()
        self._emailbox_layout = QVBoxLayout()
        self.setLayout(self._emailbox_layout)
        self._Draw()

    def _Draw(self):
        self._gb = HoverGroupBox("邮件组框")
        # 连接自定义信号到处理函数
        self._gb.mouse_hovered.connect(self._hovered)
        self._gb.mouse_left.connect(self._not_hovered)
        layout = QVBoxLayout(self._gb)
        self._emailbox_layout.addWidget(self._gb)

    def _hovered(self):
        print("鼠标悬停在组框上")

    def _not_hovered(self):
        print("鼠标离开组框")

def main():
    app: QApplication = QApplication(sys.argv)
    ex = EmailBox()
    ex.resize(400, 300)
    ex.show()
    sys.exit(app.exec())

if __name__ == "__main__":
    main()

关键说明:

  • 子类化QGroupBox,重写enterEvent和leaveEvent方法,在事件触发时发射自定义信号。
  • 使用时直接连接自定义信号到处理函数,代码结构更清晰,适合复用场景。

内容的提问来源于stack exchange,提问作者relu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 16:25:27