📄 qgraphicsscene.cpp
字号:
case Qt::IgnoreAspectRatio: break; } // Find all items to draw, and reverse the list (we want to draw // in reverse order). QList<QGraphicsItem *> itemList = items(sourceRect, Qt::IntersectsItemBoundingRect); QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()]; int numItems = itemList.size(); for (int i = 0; i < numItems; ++i) itemArray[numItems - i - 1] = itemList.at(i); itemList.clear(); painter->save(); // Transform the painter. painter->setClipRect(targetRect); painter->translate(targetRect.left(), targetRect.top()); painter->scale(xratio, yratio); painter->translate(-sourceRect.left(), -sourceRect.top()); // Two unit vectors. QLineF v1(0, 0, 1, 0); QLineF v2(0, 0, 0, 1); // Generate the style options QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems]; for (int i = 0; i < numItems; ++i) { QGraphicsItem *item = itemArray[i]; QStyleOptionGraphicsItem option; option.state = QStyle::State_None; option.rect = item->boundingRect().toRect(); if (item->isSelected()) option.state |= QStyle::State_Selected; if (item->isEnabled()) option.state |= QStyle::State_Enabled; if (item->hasFocus()) option.state |= QStyle::State_HasFocus; if (d->hoverItems.contains(item)) option.state |= QStyle::State_MouseOver; if (item == mouseGrabberItem()) option.state |= QStyle::State_Sunken; // Calculate a simple level-of-detail metric. QTransform neo = item->sceneTransform() * painter->transform(); option.levelOfDetail = ::sqrt(double(neo.map(v1).length() * neo.map(v2).length())); option.matrix = neo.toAffine(); //### discards perspective option.exposedRect = item->boundingRect(); option.exposedRect &= neo.inverted().mapRect(targetRect); styleOptionArray[i] = option; } // Render the scene. drawBackground(painter, sourceRect); drawItems(painter, numItems, itemArray, styleOptionArray); drawForeground(painter, sourceRect); delete [] itemArray; delete [] styleOptionArray; painter->restore();}/*! \property QGraphicsScene::itemIndexMethod \brief the item indexing method. QGraphicsScene applies an indexing algorithm to the scene, to speed up item discovery functions like items() and itemAt(). Indexing is most efficient for static scenes (i.e., where items don't move around). For dynamic scenes, or scenes with many animated items, the index bookkeeping can outweight the fast lookup speeds. For the common case, the default index method BspTreeIndex works fine. If your scene uses many animations and you are experiencing slowness, you can disable indexing by calling \c setItemIndexMethod(NoIndex). \sa bspTreeDepth*/QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const{ Q_D(const QGraphicsScene); return d->indexMethod;}void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method){ Q_D(QGraphicsScene); d->resetIndex(); d->indexMethod = method;}/*! \property QGraphicsScene::bspTreeDepth \brief the depth of QGraphicsScene's BSP index tree \since 4.3 This property has no effect when NoIndex is used. This value determines the depth of QGraphicsScene's BSP tree. The depth directly affects QGraphicsScene's performance and memory usage; the latter growing exponentially with the depth of the tree. With an optimal tree depth, QGraphicsScene can instantly determine the locality of items, even for scenes with thousands or millions of items. This also greatly improves rendering performance. By default, the value is 0, in which case Qt will guess a reasonable default depth based on the size, location and number of items in the scene. If these parameters change frequently, however, you may experience slowdowns as QGraphicsScene retunes the depth internally. You can avoid potential slowdowns by fixating the tree depth through setting this property. The depth of the tree and the size of the scene rectangle decide the granularity of the scene's partitioning. The size of each scene segment is determined by the following algorithm: \code QSizeF segmentSize = sceneRect().size() / pow(2, depth - 1); \endcode The BSP tree has an optimal size when each segment contains between 0 and 10 items. \sa itemIndexMethod*/int QGraphicsScene::bspTreeDepth() const{ Q_D(const QGraphicsScene); return d->bspTreeDepth;}void QGraphicsScene::setBspTreeDepth(int depth){ Q_D(QGraphicsScene); if (d->bspTreeDepth == depth) return; if (depth < 0) { qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth); return; } d->bspTreeDepth = depth; d->resetIndex();}/*! Calculates and returns the bounding rect of all items on the scene. This function works by iterating over all items, and because if this, it can be slow for large scenes. \sa sceneRect()*/QRectF QGraphicsScene::itemsBoundingRect() const{ QRectF boundingRect; foreach (QGraphicsItem *item, items()) boundingRect |= item->sceneBoundingRect(); return boundingRect;}/*! Returns a list of all items on the scene, in no particular order. \sa addItem(), removeItem()*/QList<QGraphicsItem *> QGraphicsScene::items() const{ Q_D(const QGraphicsScene); const_cast<QGraphicsScenePrivate *>(d)->purgeRemovedItems(); // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. if (d->freeItemIndexes.isEmpty()) { if (d->unindexedItems.isEmpty()) return d->indexedItems; return d->indexedItems + d->unindexedItems; } // Rebuild the list of items to avoid holes. ### We could also just // compress the item lists at this point. QList<QGraphicsItem *> itemList; foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { if (item) itemList << item; } return itemList;}/*! Returns all visible items at position \a pos in the scene. The items are listed in descending Z order (i.e., the first item in the list is the top-most item, and the last item is the bottom-most item). \sa itemAt()*/QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const{ QList<QGraphicsItem *> itemsAtPoint; // Find all items within a 1x1 rect area starting at pos. This can be // inefficient for scenes that use small coordinates (like unity // coordinates), or for detailed graphs. ### The index should support // fetching items at a pos to avoid this limitation. foreach (QGraphicsItem *item, items(QRectF(pos, QSizeF(1, 1)), Qt::IntersectsItemBoundingRect)) { if (item->contains(item->mapFromScene(pos))) itemsAtPoint << item; } return itemsAtPoint;}/*! \internal Inserts \a item into \a result if selectionPath collides with it according to \a mode.*/static void _qt_pathIntersectsItem(const QPainterPath &selectionPath, QGraphicsItem *item, Qt::ItemSelectionMode mode, QList<QGraphicsItem *> *result){ if (selectionPath.isEmpty()) return; QPainterPath path; if (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape) { path = item->mapToScene(item->shape()); } else { path.addPolygon(_q_adjustedRect(item->sceneBoundingRect())); path.closeSubpath(); } if (path.isEmpty()) return; bool intersects = selectionPath.intersects(path); if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect) { if (intersects || selectionPath.contains(path.elementAt(0)) || path.contains(selectionPath.elementAt(0))) { *result << item; } } else if (!intersects && selectionPath.contains(path.elementAt(0))) { *result << item; }}/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const \overload Returns all visible items that, depending on \a mode, are either inside or intersect with the specified \a rectangle. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a rectangle are returned. \sa itemAt()*/QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const{ Q_D(const QGraphicsScene); QList<QGraphicsItem *> itemsInRect; QPainterPath rectPath; rectPath.addRect(rect); // The index returns a rough estimate of what items are inside the rect. // Refine it by iterating through all returned items. foreach (QGraphicsItem *item, d->estimateItemsInRect(rect)) _qt_pathIntersectsItem(rectPath, item, mode, &itemsInRect); d->sortItems(&itemsInRect); return itemsInRect;}/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const \since 4.3 This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).*//*! \overload Returns all visible items that, depending on \a mode, are either inside or intersect with the polygon \a polygon. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a polygon are returned. \sa itemAt()*/QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const{ Q_D(const QGraphicsScene); QList<QGraphicsItem *> itemsInPolygon; QPainterPath polyPath; polyPath.addPolygon(polygon); polyPath.closeSubpath(); QRectF polyRect = polygon.boundingRect(); // The index returns a rough estimate of what items are inside the rect. // Refine it by iterating through all returned items. foreach (QGraphicsItem *item, d->estimateItemsInRect(polygon.boundingRect())) { if (mode == Qt::IntersectsItemBoundingRect && polygon.containsPoint(item->mapToScene(item->boundingRect().topLeft()), Qt::OddEvenFill)) { itemsInPolygon << item; } else if (polyRect.intersects(_q_adjustedRect(item->sceneBoundingRect()))) { _qt_pathIntersectsItem(polyPath, item, mode, &itemsInPolygon); } } d->sortItems(&itemsInPolygon); return itemsInPolygon;}/*! \overload Returns all visible items that, depending on \a path, are either inside or intersect with the path \a path. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a path are returned. \sa itemAt()*/QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const{ Q_D(const QGraphicsScene); QList<QGraphicsItem *> tmp; // The index returns a rough estimate of what items are inside the rect. // Refine it by iterating through all returned items. foreach (QGraphicsItem *item, d->estimateItemsInRect(path.controlPointRect())) _qt_pathIntersectsItem(path, item, mode, &tmp); d->sortItems(&tmp); return tmp;}/*! Returns a list of all items that collide with \a item. Collisions are determined by calling QGraphicsItem::collidesWithItem(); the collision detection is determined by \a mode. By default, all items whose shape intersects \a item or is contained inside \a item's shape are returned. The items are returned in descending Z order (i.e., the first item in the list is the top-most item, and the last item is the bottom-most item). \sa items(), itemAt(), QGraphicsItem::collidesWithItem()*/QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode) const{ Q_D(const QGraphicsScene); if (!item) { qWarning("QGraphicsScene::collidingItems: cannot find collisions for null item"); return QList<QGraphicsItem *>(); } QList<QGraphicsItem *> tmp; foreach (QGraphicsItem *itemInVicinity, d->estimateItemsInRect(item->sceneBoundingRect())) { if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) tmp << itemInVicinity; } d->sortItems(&tmp); return tmp;}/*! \fn QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -