Coordinate Mapping
often when dealing with items in a scene, it can be useful to map coordinates and arbitrary shapes from the scene to an item, from item to item, or from the view to the scene. For example, when you click your mouse in QGraphicsView’s viewport, you can ask the scene what item is under the cursor by calling QGraphicsView::mapToScene(), followed by QGraphicsScene::itemAt(). If you want to know where in the viewport an item is located, you can call QGraphicsItem::mapToScene() on the item, then QGraphicsView::mapFromScene() on the view. Finally, if you use want to find what items are inside a view ellipse, you can pass a QPainterPath to mapToScene(), and then pass the mapped path to QGraphicsScene::items().
You can map coordinates and shapes to and from an item’s scene by calling QGraphicsItem::mapToScene() and QGraphicsItem::mapFromScene(). You can also map to an item’s parent item by calling QGraphicsItem::mapToParent() and QGraphicsItem::mapFromParent(), or between items by calling QGraphicsItem::mapToItem() and QGraphicsItem::mapFromItem(). All mapping functions can map both points, rectangles, polygons and paths.
The same mapping functions are available in the view, for mapping to and from the scene. QGraphicsView::mapFromScene() and QGraphicsView::mapToScene(). To map from a view to an item, you first map to the scene, and then map from the scene to the item.
#include "widget.h"
#include "ui_widget.h"
#include <QWheelEvent>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QPixmap pixmap(":/images/bg.jpg");
m_scene = new QGraphicsScene(this);
m_scene->setSceneRect(0, 0, pixmap.width(), pixmap.height());
m_pixmapItem = m_scene->addPixmap(pixmap);
//Creates and adds a rectangle item to the scene, and returns the item pointer. The geometry of the rectangle is defined by rect, and its pen and brush are initialized to pen and brush.
//Note that the item's geometry is provided in item coordinates, and its position is initialized to (0, 0). For example, if a QRect(50, 50, 100, 100) is added, its top-left corner will be at (50, 50) relative to the origin in the items coordinate system. — by Qt assistent
m_rectItem = m_scene->addRect(-100, -100, 100, 100, QPen(Qt::red));//addrect属于item自身坐标系,item自身坐标系原点默认为(0, 0)
m_rectItem->setPos(50, 50);// setPos是相对于scene的坐标系
ui->graphicsView->setScene(m_scene);
ui->graphicsView->installEventFilter(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::showEvent(QShowEvent *event)
{
qDebug() << "Widget::showEvent()";
qDebug() << "in item coordinate: " << m_rectItem->boundingRect().topLeft() << ", " << m_rectItem->rect();
qDebug() << "in scene coordinate: " << m_rectItem->pos() << ", " << m_rectItem->scenePos();//pos() <===> scenePos()
qDebug() << "item map to scene coordinate: " << m_rectItem->mapToScene(m_rectItem->boundingRect().topLeft()) << ", " << m_rectItem->mapToScene(m_rectItem->boundingRect().bottomRight());
qDebug() << "item map to scene again to view coordinate:" << ui->graphicsView->mapFromScene(m_rectItem->mapToScene(m_rectItem->boundingRect().topLeft())) << ", " << ui->graphicsView->mapFromScene(m_rectItem->mapToScene(m_rectItem->boundingRect().bottomRight()));
qDebug() << "===================";
}
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
if(ui->graphicsView == obj)
{
if( QEvent::Wheel == event->type() )
{
QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
if(wheelEvent->delta() > 0)
{
ui->graphicsView->scale(1.1, 1.1);
}
else
{
ui->graphicsView->scale(1/1.1, 1/1.1);
}
}
}
return QWidget::eventFilter(obj, event);
}
void Widget::on_pushButton_clicked()
{
qDebug() << "Widget::scale()";
ui->graphicsView->scale(1.1, 1.1);
qDebug() << "in item coordinate: " << m_rectItem->boundingRect().topLeft() << ", " << m_rectItem->rect();
qDebug() << "in scene coordinate: " << m_rectItem->pos() << ", " << m_rectItem->scenePos();//pos() <===> scenePos()
qDebug() << "item mapto to scene coordinate: " << m_rectItem->mapToScene(m_rectItem->boundingRect().topLeft()) << ", " << m_rectItem->mapToScene(m_rectItem->boundingRect().bottomRight());
qDebug() << "item mapto to scene again to view coordinate:" << ui->graphicsView->mapFromScene(m_rectItem->mapToScene(m_rectItem->boundingRect().topLeft())) << ", " << ui->graphicsView->mapFromScene(m_rectItem->mapToScene(m_rectItem->boundingRect().bottomRight()));
qDebug() << "=======================";
}
void Widget::on_pushButton_2_clicked()
{
ui->graphicsView->scale(1/1.1, 1/1.1);
}
void Widget::on_pushButton_3_clicked()
{
ui->graphicsView->rotate(10);
qDebug() << "in item coordinate: " << m_rectItem->boundingRect().topLeft() << ", " << m_rectItem->rect();
qDebug() << "in scene coordinate: " << m_rectItem->pos() << ", " << m_rectItem->scenePos();//pos() <===> scenePos()
qDebug() << "item mapto to scene coordinate: " << m_rectItem->mapToScene(m_rectItem->boundingRect().topLeft()) << ", " << m_rectItem->mapToScene(m_rectItem->boundingRect().bottomRight());
qDebug() << "item mapto to scene again to view coordinate:" << ui->graphicsView->mapFromScene(m_rectItem->mapToScene(m_rectItem->boundingRect().topLeft())) << ", " << ui->graphicsView->mapFromScene(m_rectItem->mapToScene(m_rectItem->boundingRect().bottomRight()));
qDebug() << "=======================";
}
void Widget::on_pushButton_4_clicked()
{
ui->graphicsView->rotate(-10);
}
最后的结论,读者可自行推导出。