📄 qgraphicsview.cpp
字号:
\overload This convenience function is equivalent to calling fitInView(QRectF(\a x, \a y, \a w, \a h), \a aspectRatioMode). \sa ensureVisible(), centerOn()*//*! \overload Ensures that \a item fits tightly inside the view, scaling the view according to \a aspectRatioMode. \sa ensureVisible(), centerOn()*/void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode){ fitInView(item->sceneTransform().map(item->shape()).boundingRect(), aspectRatioMode);}/*! Renders the \a source rect, which is in view coordinates, from the scene into \a target, which is in paint device coordinates, using \a painter. This function is useful for capturing the contents of the view onto a paint device, such as a QImage (e.g., to take a screenshot), or for printing to QPrinter. For example: \code QGraphicsScene scene; scene.addItem(... ... QGraphicsView view(&scene); view.show(); ... QPrinter printer(QPrinter::HighResolution); printer.setPageSize(QPrinter::A4); QPainter painter(&printer); // print, fitting the viewport contents into a full page view.render(&painter); // print the upper half of the viewport into the lower. // half of the page. QRect viewport = view.viewport()->rect(); view.render(&painter, QRectF(0, printer.height() / 2, printer.width(), printer.height() / 2), viewport.adjusted(0, 0, 0, -viewport.height() / 2)); \endcode If \a source is a null rect, this function will use viewport()->rect() to determine what to draw. If \a target is a null rect, the full dimensions of \a painter's paint device (e.g., for a QPrinter, the page size) will be used. The source rect contents will be transformed according to \a aspectRatioMode to fit into the target rect. By default, the aspect ratio is kept, and \a source is scaled to fit in \a target. \sa QGraphicsScene::render()*/void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect &source, Qt::AspectRatioMode aspectRatioMode){ Q_D(QGraphicsView); if (!d->scene) return; // Default source rect = viewport rect QRect sourceRect = source; if (source.isNull()) sourceRect = viewport()->rect(); // Default target rect = device rect QRectF targetRect = target; if (target.isNull()) { if (painter->device()->devType() == QInternal::Picture) targetRect = sourceRect; else targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height()); } // Find the ideal x / y scaling ratio to fit \a source into \a target. qreal xratio = targetRect.width() / sourceRect.width(); qreal yratio = targetRect.height() / sourceRect.height(); // Scale according to the aspect ratio mode. switch (aspectRatioMode) { case Qt::KeepAspectRatio: xratio = yratio = qMin(xratio, yratio); break; case Qt::KeepAspectRatioByExpanding: xratio = yratio = qMax(xratio, yratio); break; case Qt::IgnoreAspectRatio: break; } // Find all items to draw, and reverse the list (we want to draw // in reverse order). QPolygonF sourceScenePoly = mapToScene(sourceRect.adjusted(-1, -1, 1, 1)); QList<QGraphicsItem *> itemList = d->scene->items(sourceScenePoly, 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(); // Setup painter matrix. QTransform moveMatrix; moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll()); QTransform painterMatrix = d->matrix * moveMatrix; painterMatrix *= QTransform() .translate(targetRect.left(), targetRect.top()) .scale(xratio, yratio) .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->scene->d_func()->hoverItems.contains(item)) option.state |= QStyle::State_MouseOver; if (item == d->scene->mouseGrabberItem()) option.state |= QStyle::State_Sunken; // Calculate a simple level-of-detail metric. QTransform neo = item->sceneTransform() * painterMatrix; QTransform lodMatrix = neo * painter->worldTransform(); option.levelOfDetail = ::sqrt(double(lodMatrix.map(v1).length() * lodMatrix.map(v2).length())); option.matrix = neo.toAffine(); option.exposedRect = item->boundingRect(); option.exposedRect &= neo.inverted().mapRect(targetRect); styleOptionArray[i] = option; } painter->save(); // Clip in device coordinates to avoid QRegion transformations. painter->setClipRect(targetRect); QPainterPath path; path.addPolygon(sourceScenePoly); path.closeSubpath(); painter->setClipPath(painterMatrix.map(path), Qt::IntersectClip); // Transform the painter. painter->setTransform(painterMatrix, true); // Render the scene. QRectF sourceSceneRect = sourceScenePoly.boundingRect(); drawBackground(painter, sourceSceneRect); drawItems(painter, numItems, itemArray, styleOptionArray); drawForeground(painter, sourceSceneRect); delete [] itemArray; delete [] styleOptionArray; painter->restore();}/*! Returns a list of all the items in the associated scene. \sa QGraphicsScene::items()*/QList<QGraphicsItem *> QGraphicsView::items() const{ Q_D(const QGraphicsView); if (!d->scene) return QList<QGraphicsItem *>(); return d->scene->items();}/*! Returns all items in the area \a path, which is in viewport coordinates, also taking untransformable items into consideration. This function is considerably slower than just checking the scene directly. There is certainly room for improvement.*/QList<QGraphicsItem *> QGraphicsViewPrivate::itemsInArea(const QPainterPath &path, Qt::ItemSelectionMode mode) const{ Q_Q(const QGraphicsView); // Determine the size of the largest untransformable subtree of children // mapped to scene coordinates. QRectF untr = scene->d_func()->largestUntransformableItem; QRectF ltri = matrix.inverted().mapRect(untr); ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height()); QRectF rect = path.controlPointRect(); // Find all possible items in the relevant area. // ### Improve this algorithm; it might be searching a too large area. QRectF adjustedRect = q->mapToScene(rect.adjusted(-1, -1, 1, 1).toRect()).boundingRect(); adjustedRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height()); // First build a (potentially large) list of all items in the vicinity // that might be untransformable. QList<QGraphicsItem *> allCandidates = scene->d_func()->estimateItemsInRect(adjustedRect); // Then find the minimal list of items that are inside \a path, and // convert it to a set. QList<QGraphicsItem *> regularCandidates = scene->items(q->mapToScene(path), mode); QSet<QGraphicsItem *> candSet = QSet<QGraphicsItem *>::fromList(regularCandidates); QTransform viewMatrix = q->viewportTransform(); QList<QGraphicsItem *> result; // Run through all candidates and keep all items that are in candSet, or // are untransformable and collide with \a path. ### We can improve this // algorithm. QList<QGraphicsItem *>::Iterator it = allCandidates.begin(); while (it != allCandidates.end()) { QGraphicsItem *item = *it; if (item->d_ptr->itemIsUntransformable()) { // Check if this untransformable item collides with the // original selection rect. QTransform itemTransform = item->deviceTransform(viewMatrix); if (item->collidesWithPath(itemTransform.inverted().map(path), mode)) result << item; } else { if (candSet.contains(item)) result << item; } ++it; } // ### Insertion sort would be faster. QGraphicsScenePrivate::sortItems(&result); return result;}/*! Returns a list of all the items at the position \a pos in the view. 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). \a pos is in viewport coordinates. This function is most commonly called from within mouse event handlers in a subclass in QGraphicsView. \a pos is in untransformed viewport coordinates, just like QMouseEvent::pos(). \code void CustomView::mousePressEvent(QMouseEvent *event) { qDebug() << "There are" << items(event->pos()).size() << "items at position" << mapToScene(event->pos()); } \endcode \sa QGraphicsScene::items(), QGraphicsItem::zValue()*/QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const{ Q_D(const QGraphicsView); if (!d->scene) return QList<QGraphicsItem *>(); if (d->scene->d_func()->largestUntransformableItem.isNull()) return d->scene->items(mapToScene(pos.x(), pos.y(), 2, 2)); QPainterPath path; path.addRect(QRectF(pos.x(), pos.y(), 1, 1)); return d->itemsInArea(path);}/*! \fn QGraphicsView::items(int x, int y) const This function is provided for convenience. It's equivalent to calling items(QPoint(\a x, \a y)).*//*! \overload Returns a list of all the items that, depending on \a mode, are either contained by or intersect with \a rect. \a rect is in viewport coordinates. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a rect are returned. \sa itemAt(), items(), mapToScene()*/QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const{ Q_D(const QGraphicsView); if (!d->scene) return QList<QGraphicsItem *>(); if (d->scene->d_func()->largestUntransformableItem.isNull()) return d->scene->items(mapToScene(rect), mode); QPainterPath path; path.addRect(rect); return d->itemsInArea(path);}/*! \fn QList<QGraphicsItem *> QGraphicsView::items(int x, int y, int w, int 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 a list of all the items that, depending on \a mode, are either contained by or intersect with \a polygon. \a polygon is in viewport coordinates. 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(), items(), mapToScene()*/QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const{ Q_D(const QGraphicsView); if (!d->scene) return QList<QGraphicsItem *>(); if (d->scene->d_func()->largestUntransformableItem.isNull()) return d->scene->items(mapToScene(polygon), mode); QPainterPath path; path.addPolygon(polygon); path.closeSubpath(); return d->itemsInArea(path);}/*! \overload Returns a list of all the items that, depending on \a mode, are either contained by or intersect with \a path. \a path is in viewport coordinates. 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(), items(), mapToScene()*/QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const{ Q_D(const QGraphicsView); if (!d->scene) return QList<QGraphicsItem *>(); if (d->scene->d_func()->largestUntransformableItem.isNull()) return d->scene->items(mapToScene(path), mode); return d->itemsInArea(path);}/*! Returns the item at position \a pos, which is in viewport coordinates. If there are several items at this position, this function returns the topmost item. Exampl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -