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

Qt中QPushButton的HoverEnter事件仅点击后生效的问题求助

解决QPushButton在QGraphicsScene中HoverEnter事件需点击才触发的问题

问题现象

  • 将自定义QPushButton(已设置Qt::WA_Hover属性)添加到QGraphicsScene后,未点击按钮时无法触发HoverEnter/HoverLeave事件,仅点击按钮使其获得焦点后,hover事件才正常生效
  • 提供的最小示例代码可正常运行,但实际项目中未点击时仅能收到UpdateRequest、Paint等事件,无hover事件触发

核心原因

QWidget被添加到QGraphicsScene时,会自动被QGraphicsProxyWidget包裹,而默认情况下代理部件未启用hover事件转发。只有当内部QWidget获得焦点(点击操作)后,代理才会开始将hover事件传递给它,导致未点击时hover事件丢失。

解决方案

方案1:给代理部件启用hover属性

在将按钮添加到场景后,获取对应的代理部件,手动开启Qt::WA_Hover属性:

hoverBut* but = new hoverBut;
// 添加按钮到场景并获取代理
QGraphicsProxyWidget* proxy = scene->addWidget(but);
// 给代理启用hover属性
proxy->setAttribute(Qt::WA_Hover);

方案2:重写QGraphicsScene转发hover事件

如果场景内有多个需要hover响应的部件,可自定义QGraphicsScene,手动将场景级的hover事件转发给对应部件的代理:

class CustomScene : public QGraphicsScene
{
protected:
    void hoverEnterEvent(QGraphicsSceneHoverEvent* event) override
    {
        QGraphicsItem* targetItem = itemAt(event->scenePos(), QTransform());
        if (auto proxyWidget = qgraphicsitem_cast<QGraphicsProxyWidget*>(targetItem)) {
            // 构造HoverEnter事件并发送给内部QWidget
            QHoverEvent hoverEnterEvent(QEvent::HoverEnter,
                                       proxyWidget->mapFromScene(event->scenePos()),
                                       event->screenPos());
            QCoreApplication::sendEvent(proxyWidget->widget(), &hoverEnterEvent);
        }
        QGraphicsScene::hoverEnterEvent(event);
    }

    void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override
    {
        QGraphicsItem* targetItem = itemAt(event->scenePos(), QTransform());
        if (auto proxyWidget = qgraphicsitem_cast<QGraphicsProxyWidget*>(targetItem)) {
            // 构造HoverLeave事件并发送给内部QWidget
            QHoverEvent hoverLeaveEvent(QEvent::HoverLeave,
                                       proxyWidget->mapFromScene(event->scenePos()),
                                       event->screenPos());
            QCoreApplication::sendEvent(proxyWidget->widget(), &hoverLeaveEvent);
        }
        QGraphicsScene::hoverLeaveEvent(event);
    }
};

之后使用CustomScene替代默认的QGraphicsScene即可。

方案3:改用QGraphicsWidget实现按钮

如果项目场景允许,直接继承QGraphicsWidget实现自定义按钮,它原生支持QGraphicsScene的hover事件机制,无需处理代理部件的转发问题。

关键验证点

  • 确保QGraphicsView已启用鼠标跟踪:view->setMouseTracking(true);(默认关闭,仅鼠标按下时才跟踪位置)
  • 检查自定义按钮的Qt::WA_Hover属性是否被其他代码意外覆盖

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:44:54