Вот как я обрабатываю столкновение двух графических элементов. Он вызывается в mouseMoveEvent и itemChange. Вот так:
void GraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
auto delta = event->pos() - event->lastPos();
auto new_pos = handleCollisions(pos() + delta);
setPos(new_pos);
}
Функция new_pos такова, что я могу вызвать ее в itemChange и вернуть ее в качестве значения. Однако эта версия обработки столкновений оставляет new_pos без изменений. Вместо этого мы перемещаем элементы, которые сталкиваются с этим (как мы перемещаем этот с помощью мыши). Я пытаюсь взять пересечение двух вовлеченных ограничивающих линий и сдвинуть другое на более короткое измерение пересечения прямоугольников. Результатом, который является неожиданным, является то, что прямоугольники движутся не только на это небольшое количество, а вместо этого по всей ширине (или высоте) любого из boundingRects () (они имеют одинаковый размер). Я объяснил это тем, что приведенный ниже код, который вычисляет пересечение ограничивающих сторон в пространстве позиции родителя (где pos (), setPos () относительно), неверен.
Так как мне это сделать?
Вот картинка того, что я хочу:
QPointF GraphicsItem::handleCollisions(const QPointF& new_pos) const {
auto collisions = collidingItems();
auto rect = mapToParent(boundingRect().translated(new_pos - pos())).boundingRect();
for(int k=0; k < collisions.count(); k++)
{
auto item = collisions[k];
if (item->parentItem() == parentItem()) {
auto rect1 = mapToParent(item->boundingRect()).boundingRect();
rect1 = rect1.intersected(rect);
qDebug() << (rect1.width());
qDebug() << (rect1.height());
auto v = rect1.center() - rect.center();
if (v.x() >= 0) {
if (v.y() >= 0) {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(-rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, -rect1.height()));
}
else {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, rect1.height()));
}
}
else {
if (v.y() >= 0) {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, -rect1.height()));
}
else {
if (rect1.width() <= rect1.height())
item->setPos(item->pos() + QPointF(rect1.width(), 0));
else
item->setPos(item->pos() + QPointF(0, rect1.height()));
}
}
}
}
return new_pos; // return this position unchanged
}