座标系统之item、scene、view三者映射关系

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);
}

最后的结论,读者可自行推导出。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值