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

如何在弃用setHandlesChildEvents时传递QGraphicsItemGroup鼠标事件给子元素

QGraphicsItemGroup鼠标事件传递给子项的解决方案(替代已弃用的setHandlesChildEvents)

你的代码没生效主要有几个问题:直接用sendEvent传递原始事件会导致状态异常、强制转换子项不安全、重写sceneEvent时直接返回true阻断了父类默认处理逻辑。下面给你两种可行的实现方式:

方法一:重写具体鼠标事件,定向转发给子项

这种方式针对特定事件(比如双击)进行处理,先让符合条件的子项接收事件:

class MoveItemBase : public QObject, public QGraphicsItemGroup
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)
public:
    explicit MoveItemBase(QGraphicsItem *parent = nullptr) : QGraphicsItemGroup(parent) {}

protected:
    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override
    {
        // 遍历子项,找到事件位置上的可交互子项
        for (QGraphicsItem *child : childItems()) {
            if (!child->isEnabled() || !child->acceptsHoverEvents()) continue;
            
            QPointF childPos = mapToChild(event->pos());
            if (child->contains(childPos)) {
                // 复制事件并转换坐标到子项坐标系
                QGraphicsSceneMouseEvent childEvent(*event);
                childEvent.setPos(childPos);
                // 让子项处理事件
                child->mouseDoubleClickEvent(&childEvent);
                
                // 如果子项标记事件已处理,就终止传递
                if (childEvent.isAccepted()) {
                    event->setAccepted(true);
                    return;
                }
            }
        }
        // 没有子项处理时,执行父类默认逻辑
        QGraphicsItemGroup::mouseDoubleClickEvent(event);
    }
};

方法二:给子项安装事件过滤器,灵活控制事件

如果需要监听多种事件或者更精细的控制,可以用事件过滤器:

class MoveItemBase : public QObject, public QGraphicsItemGroup
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)
public:
    explicit MoveItemBase(QGraphicsItem *parent = nullptr) : QGraphicsItemGroup(parent) {}

    void addItem(QGraphicsItem *item) override
    {
        QGraphicsItemGroup::addItem(item);
        // 给继承QObject的子项安装过滤器(非QObject子类无法使用)
        if (QObject *childObj = qobject_cast<QObject*>(item)) {
            childObj->installEventFilter(this);
        }
    }

protected:
    bool eventFilter(QObject *watched, QEvent *event) override
    {
        if (event->type() == QEvent::GraphicsSceneMouseDoubleClick) {
            // 这里可以插入你的自定义逻辑,比如日志、状态更新
            // 返回false让子项继续处理事件,返回true则拦截
            return false;
        }
        return QGraphicsItemGroup::eventFilter(watched, event);
    }
};

核心注意事项

  • 必须转换事件坐标:父item的事件坐标是自身坐标系,要转成子项的局部坐标才能让子项正确识别事件位置;
  • 安全类型转换:用qobject_cast替代static_cast,转换后做空指针检查,避免崩溃;
  • 保留父类默认逻辑:不要随意阻断事件的默认处理流程,除非你明确不需要。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:00:14