📄 qgraphicsscene.cpp
字号:
{ dragDropEvent->setPos(item->d_ptr->genericMapFromScene(dragDropEvent->scenePos(), dragDropEvent->widget())); sendEvent(item, dragDropEvent);}/*! \internal*/void QGraphicsScenePrivate::sendHoverEvent(QEvent::Type type, QGraphicsItem *item, QGraphicsSceneHoverEvent *hoverEvent){ QGraphicsSceneHoverEvent event(type); event.setWidget(hoverEvent->widget()); event.setPos(item->d_ptr->genericMapFromScene(hoverEvent->scenePos(), hoverEvent->widget())); event.setScenePos(hoverEvent->scenePos()); event.setScreenPos(hoverEvent->screenPos()); sendEvent(item, &event);}/*! \internal*/void QGraphicsScenePrivate::sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent){ if (mouseEvent->button() == 0 && mouseEvent->buttons() == 0) { // ### This is a temporary fix for until we get proper mouse // grab events. mouseGrabberItem should be set to 0 if the // view loses mouse grab. mouseGrabberItem = 0; return; } for (int i = 0x1; i <= 0x10; i <<= 1) { Qt::MouseButton button = Qt::MouseButton(i); mouseEvent->setButtonDownPos(button, mouseGrabberButtonDownPos.value(button, mouseGrabberItem->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget()))); mouseEvent->setButtonDownScenePos(button, mouseGrabberButtonDownScenePos.value(button, mouseEvent->scenePos())); mouseEvent->setButtonDownScreenPos(button, mouseGrabberButtonDownScreenPos.value(button, mouseEvent->screenPos())); } mouseEvent->setPos(mouseGrabberItem->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget())); mouseEvent->setLastPos(mouseGrabberItem->d_ptr->genericMapFromScene(mouseEvent->lastScenePos(), mouseEvent->widget())); sendEvent(mouseGrabberItem, mouseEvent);}/*! \internal*/void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent){ Q_Q(QGraphicsScene); if (mouseGrabberItem) { // We already have a mouse grabber. This means more than one button is // pressed at the same time. This is just delivered like a normal // event. sendMouseEvent(mouseEvent); return; } // Ignore by default, unless we find a mouse grabber that accepts it. mouseEvent->ignore(); // Start by determining the number of items at the current position. // Reuse value from earlier calculations if possible. if (cachedItemsUnderMouse.isEmpty()) { cachedItemsUnderMouse = itemsAtPosition(mouseEvent->screenPos(), mouseEvent->scenePos(), mouseEvent->widget()); } // Set focus on the topmost enabled item that can take focus. bool setFocus = false; foreach (QGraphicsItem *item, cachedItemsUnderMouse) { if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { setFocus = true; if (item != q->focusItem()) q->setFocusItem(item, Qt::MouseFocusReason); break; } } // If nobody could take focus, we clear it. if (!setFocus) q->setFocusItem(0, Qt::MouseFocusReason); // Find a mouse grabber by sending mouse press events to all mouse grabber // candidates one at a time, until the event is accepted. It's accepted by // default, so the receiver has to explicitly ignore it for it to pass // through. foreach (QGraphicsItem *item, possibleMouseGrabbersForEvent(cachedItemsUnderMouse, mouseEvent)) { mouseGrabberItem = item; mouseEvent->accept(); if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick && item != lastMouseGrabberItem) { // If this item is different from the item that received the last // mouse event, and mouseEvent is a doubleclick event, then the // event is converted to a press. Known limitation: // Triple-clicking will not generate a doubleclick, though. QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress); mousePress.accept(); mousePress.setButton(mouseEvent->button()); mousePress.setButtons(mouseEvent->buttons()); mousePress.setScreenPos(mouseEvent->screenPos()); mousePress.setScenePos(mouseEvent->scenePos()); mousePress.setModifiers(mouseEvent->modifiers()); sendMouseEvent(&mousePress); mouseEvent->setAccepted(mousePress.isAccepted()); } else { sendMouseEvent(mouseEvent); } if (mouseEvent->isAccepted()) { if (mouseGrabberItem) storeMouseButtonsForMouseGrabber(mouseEvent); lastMouseGrabberItem = mouseGrabberItem; return; } } // Is the event still ignored? Then the mouse press goes to the scene. // Reset the mouse grabber, clear the selection, clear focus, and leave // the event ignored so that it can propagate through the originating // view. if (!mouseEvent->isAccepted()) { lastMouseGrabberItem = mouseGrabberItem; QGraphicsView *view = mouseEvent->widget() ? qobject_cast<QGraphicsView *>(mouseEvent->widget()->parentWidget()) : 0; bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag; if (!dontClearSelection) { // Clear the selection if the originating view isn't in scroll // hand drag mode. The view will clear the selection if no drag // happened. q->clearSelection(); } }}/*! \internal*/inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2){ qreal z1 = item1->d_ptr->z; qreal z2 = item2->d_ptr->z; return z1 != z2 ? z1 > z2 : item1 > item2;}/*! \internal*/bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2){ // Siblings? Just check their z-values. if (item1->d_ptr->parent == item2->d_ptr->parent) return qt_closestLeaf(item1, item2); // Find item1's ancestors. If item2 is among them, return true (item1 is // above item2). QVector<const QGraphicsItem *> ancestors1; const QGraphicsItem *parent1 = item1; do { if (parent1 == item2) return true; ancestors1.prepend(parent1); } while ((parent1 = parent1->d_ptr->parent)); // Find item2's ancestors. If item1 is among them, return false (item2 is // above item1). QVector<const QGraphicsItem *> ancestors2; const QGraphicsItem *parent2 = item2; do { if (parent2 == item1) return false; ancestors2.prepend(parent2); } while ((parent2 = parent2->d_ptr->parent)); // Truncate the largest ancestor list. int size1 = ancestors1.size(); int size2 = ancestors2.size(); if (size1 > size2) { ancestors1.resize(size2); } else if (size2 > size1) { ancestors2.resize(size1); } // Compare items from the two ancestors lists and find a match. Then // compare item1's and item2's toplevels relative to the common ancestor. for (int i = ancestors1.size() - 2; i >= 0; --i) { const QGraphicsItem *a1 = ancestors1.at(i); const QGraphicsItem *a2 = ancestors2.at(i); if (a1 == a2) return qt_closestLeaf(ancestors1.at(i + 1), ancestors2.at(i + 1)); } // No common ancestor? Then just compare the items' toplevels directly. return qt_closestLeaf(ancestors1.first(), ancestors2.first());}/*! \internal*/void QGraphicsScenePrivate::sortItems(QList<QGraphicsItem *> *itemList){ qSort(itemList->begin(), itemList->end(), qt_closestItemFirst);}/*! Constructs a QGraphicsScene object. The \a parent parameter is passed to QObject's constructor.*/QGraphicsScene::QGraphicsScene(QObject *parent) : QObject(*new QGraphicsScenePrivate, parent){ update();}/*! Constructs a QGraphicsScene object, using \a sceneRect for its scene rectangle. The \a parent parameter is passed to QObject's constructor. \sa sceneRect*/QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent) : QObject(*new QGraphicsScenePrivate, parent){ setSceneRect(sceneRect); update();}/*! Constructs a QGraphicsScene object, using the rectangle specified by (\a x, \a y), and the given \a width and \a height for its scene rectangle. The \a parent parameter is passed to QObject's constructor. \sa sceneRect*/QGraphicsScene::QGraphicsScene(qreal x, qreal y, qreal width, qreal height, QObject *parent) : QObject(*new QGraphicsScenePrivate, parent){ setSceneRect(x, y, width, height); update();}/*! Destroys the QGraphicsScene object.*/QGraphicsScene::~QGraphicsScene(){ Q_D(QGraphicsScene); for (int i = 0; i < d->unindexedItems.size(); ++i) { if (QGraphicsItem *item = d->unindexedItems[i]) { d->unindexedItems[i] = 0; d->removeFromIndex(item); item->d_func()->scene = 0; delete item; } } for (int i = 0; i < d->indexedItems.size(); ++i) { if (QGraphicsItem *item = d->indexedItems[i]) { if (!d->removedItems.contains(item)) { d->indexedItems[i] = 0; d->removeFromIndex(item); item->d_func()->scene = 0; delete item; } } } // Remove this scene from all associated views. for (int j = 0; j < d->views.size(); ++j) d->views.at(j)->setScene(0);}/*! \property QGraphicsScene::sceneRect \brief the scene rectangle; the bounding rectangle of the scene The scene rectangle defines the extent of the scene. It is primarily used by QGraphicsView to determine the view's default scrollable area, and by QGraphicsScene to manage item indexing. If unset, or if set to a null QRectF, sceneRect() will return the largest bounding rect of all items on the scene since the scene was created (i.e., a rectangle that grows when items are added to or moved in the scene, but never shrinks). \sa width(), height(), QGraphicsView::sceneRect*/QRectF QGraphicsScene::sceneRect() const{ Q_D(const QGraphicsScene); const_cast<QGraphicsScenePrivate *>(d)->_q_generateBspTree(); return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect;}void QGraphicsScene::setSceneRect(const QRectF &rect){ Q_D(QGraphicsScene); if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; d->resetIndex(); emit sceneRectChanged(rect); }}/*! \fn qreal QGraphicsScene::width() const This convenience function is equivalent to calling sceneRect().width(). \sa height()*//*! \fn qreal QGraphicsScene::height() const This convenience function is equivalent to calling \c sceneRect().height(). \sa width()*//*! Renders the \a source rect from scene into \a target, using \a painter. This function is useful for capturing the contents of the scene onto a paint device, such as a QImage (e.g., to take a screenshot), or for printing with QPrinter. For example: \code QGraphicsScene scene; scene.addItem(... ... QPrinter printer(QPrinter::HighResolution); printer.setPageSize(QPrinter::A4); QPainter painter(&printer); scene.render(&painter); \endcode If \a source is a null rect, this function will use sceneRect() to determine what to render. If \a target is a null rect, the dimensions of \a painter's paint device 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 QGraphicsView::render()*/void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source, Qt::AspectRatioMode aspectRatioMode){ Q_D(QGraphicsScene); // Default source rect = scene rect QRectF sourceRect = source; if (sourceRect.isNull()) sourceRect = sceneRect(); // Default target rect = device rect QRectF targetRect = target; if (targetRect.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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -