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

Qt自定义QGraphicsItem移动时itemChange方法未触发问题

QGraphicsItem移动时itemChange不触发网格吸附的解决方案

问题原因

  1. 未启用几何变化通知标志:QGraphicsItem默认不会主动发送位置变化的事件通知,必须显式开启ItemSendsGeometryChanges标志,itemChange才能在拖动时捕获ItemPositionChange事件。
  2. 吸附逻辑错误:原代码使用当前位置this->x()/this->y()计算吸附坐标,但ItemPositionChange触发时,当前位置并未更新,应该使用回调传入的value参数(即拖动的目标位置)来计算。

修复方案

1. 添加几何变化通知标志

在SceneObject构造函数中新增ItemSendsGeometryChanges标志的设置:

SceneObject::SceneObject(int width, int height, QPen pen, QBrush brush)
{
    this->rect = QRect(0, 0, width, height);
    this->pen = pen;
    this->brush = brush;
    this->setFlag(GraphicsItemFlag::ItemIsMovable);
    this->setFlag(GraphicsItemFlag::ItemSendsGeometryChanges); // 启用几何变化通知
}

2. 修正网格吸附计算逻辑

修改itemChange方法,使用传入的目标位置计算吸附坐标:

QVariant SceneObject::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) {
    qDebug() << "Something happened, " << "Value: " << value;
    if (change == ItemPositionChange) {
        qDebug() << "Item was moved, " << "Value: " << value;
        int CELL_SIZE = Globals::CELL_SIZE;
        QPointF targetPos = value.toPointF();
        // 基于拖动的目标位置计算网格吸附后的坐标
        qreal snappedX = floor(targetPos.x() / CELL_SIZE) * CELL_SIZE;
        qreal snappedY = floor(targetPos.y() / CELL_SIZE) * CELL_SIZE;
        return QPointF(snappedX, snappedY);
    }
    return QGraphicsItem::itemChange(change, value);
}

说明

  • ItemSendsGeometryChanges是触发移动时itemChange回调的核心前提,没有这个标志,拖动操作不会触发ItemPositionChange事件。
  • 使用value中的目标位置计算吸附坐标,能保证吸附逻辑准确跟随用户的拖动操作,避免因当前位置未更新导致的偏移问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 01:40:25