坐标点确定是没问题的,就是item所在的位置
看源码,基于5.9.7
Src\qtbase\src\widgets\graphicsview\qgraphicsview.cpp
QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const
{
Q_D(const QGraphicsView);
if (!d->scene)
return 0;
const QList<QGraphicsItem *> itemsAtPos = items(pos);
return itemsAtPos.isEmpty() ? 0 : itemsAtPos.first();
}
QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
{
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
// ### Unify these two, and use the items(QPointF) version in
// QGraphicsScene instead. The scene items function could use the viewport
// transform to map the point to a rect/polygon.
if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
// Use the rect version
QTransform xinv = viewportTransform().inverted();
return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)),
Qt::IntersectsItemShape,
Qt::DescendingOrder,
viewportTransform());
}
// Use the polygon version
return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1),
Qt::IntersectsItemShape,
Qt::DescendingOrder,
viewportTransform());
}
Src\qtbase\src\widgets\graphicsview\qgraphicsscene.cpp
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode,
Qt::SortOrder order, const QTransform &deviceTransform) const
{
Q_D(const QGraphicsScene);
return d->index->items(pos, mode, order, deviceTransform);
}
Src\qtbase\src\widgets\graphicsview\qgraphicssceneindex.cpp
QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode,
Qt::SortOrder order, const QTransform &deviceTransform) const
{
Q_D(const QGraphicsSceneIndex);
QList<QGraphicsItem *> itemList;
d->items_helper(QRectF(pos, QSizeF(1, 1)), &QtPrivate::intersect_point, &itemList, deviceTransform, mode, order, &pos);
return itemList;
}
QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const
{
Q_D(const QGraphicsSceneIndex);
Q_UNUSED(rect);
QGraphicsScenePrivate *scened = d->scene->d_func();
scened->ensureSortedTopLevelItems();
if (order == Qt::DescendingOrder) {
QList<QGraphicsItem *> sorted;
const int numTopLevelItems = scened->topLevelItems.size();
sorted.reserve(numTopLevelItems);
for (int i = numTopLevelItems - 1; i >= 0; --i)
sorted << scened->topLevelItems.at(i);
return sorted;
}
return scened->topLevelItems;
}
void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
QGraphicsSceneIndexIntersector intersect,
QList<QGraphicsItem *> *items,
const QTransform &viewTransform,
Qt::ItemSelectionMode mode,
qreal parentOpacity, const void *intersectData) const
{
...
}
Src\qtbase\src\widgets\graphicsview\qgraphicssceneindex_p.h
class QGraphicsSceneIndexPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QGraphicsSceneIndex)
public:
QGraphicsSceneIndexPrivate(QGraphicsScene *scene);
~QGraphicsSceneIndexPrivate();
void init();
static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode);
void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
QGraphicsSceneIndexIntersector intersect, QList<QGraphicsItem *> *items,
const QTransform &viewTransform,
Qt::ItemSelectionMode mode, qreal parentOpacity, const void *intersectData) const;
inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector intersect,
QList<QGraphicsItem *> *items, const QTransform &viewTransform,
Qt::ItemSelectionMode mode, Qt::SortOrder order, const void *intersectData) const;
QGraphicsScene *scene;
};
inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector intersect,
QList<QGraphicsItem *> *items, const QTransform &viewTransform,
Qt::ItemSelectionMode mode, Qt::SortOrder order, const void *intersectData) const
{
Q_Q(const QGraphicsSceneIndex);
const QList<QGraphicsItem *> tli = q->estimateTopLevelItems(rect, Qt::AscendingOrder);
for (int i = 0; i < tli.size(); ++i)
recursive_items_helper(tli.at(i), rect, intersect, items, viewTransform, mode, 1.0, intersectData);
if (order == Qt::DescendingOrder) {
const int n = items->size();
for (int i = 0; i < n / 2; ++i)
items->swap(i, n - i - 1);
}
}
recursive_items_helper里面没有再深入研究了,至此可以知道QGraphicsView和QGraphicsScene的itemAt内部都是QGraphicsScene::items,然后看QGraphicsItem::shape()的说明
Returns the shape of this item as a QPainterPath in local coordinates. The shape is used for many things, including collision detection, hit tests, and for the QGraphicsScene::items() functions.
The outline of a shape can vary depending on the width and style of the pen used when drawing
看QGraphicsItem::boundingRect()的说明
This pure virtual function defines the outer bounds of the item as a rectangle; all painting must be restricted to inside an item’s bounding rect. QGraphicsView uses this to determine whether the item requires redrawing.
Note: For shapes that paint an outline / stroke, it is important to include half the pen width in the bounding rect. It is not necessary to compensate for antialiasing, though.
问题就出在QGraphicsItem::shape(),自己重写的shape里计算结果超出boundingRect了,导致QGraphicsScene::items() 无法正确定位item
3208

被折叠的 条评论
为什么被折叠?



