一、视图(QGraphicsView)的坐标
视图将窗口中的左上角作为原点(0,0),不弄窗口大小,原点总是在左上角。向右为X轴正方向,向下为Y轴正方向。如下图所示:
二、场景(QGraphicsScene)的坐标
通常情况下场景的坐标原点(0,0)在场景的的中心位置。向右为X轴的正方向,向下为Y轴的正方向,如下图所示:
场景通过void setSceneRect(qreal x, qreal y, qreal w, qreal h)
来设置场景的坐标以及大小。其中x和y用于设定场景左上角的坐标,w和h来设定场景的大小。先分析下面代码:
main.cpp
#include <QApplication>
#include "butterfly.h"
#include <QGraphicsScene>
#include <QPointF>
#include <QMainWindow>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene *scene = new QGraphicsScene;
scene->setSceneRect(0, 0, 400, 400);
Butterfly *butterfly = new Butterfly();
butterfly->setPos(scene->sceneRect().left(), scene->sceneRect().top());
scene->addItem(butterfly);
QGraphicsView *view = new QGraphicsView;
view->setScene(scene);
view->show();
// 视图坐标原点(0,0)对应场景坐标(场景坐标)
qDebug() << "view->mapToScene(0, 0):" << view->mapToScene(0, 0);
// 场景坐标原点(0,0)对应视图坐标(视图坐标)
qDebug() << "view->mapFromScene(0, 0):" << view->mapFromScene(0, 0);
// 场景左上角坐标(场景坐标)
QPointF p1 = QPointF(scene->sceneRect().topLeft());
qDebug() << "p1:" << p1;
// 场景左上角对应视图坐标(视图坐标)
qDebug() << "view->mapFromScene(p1.x(), p1.y())" << view->mapFromScene(p1.x(), p1.y());
return a.exec();
}
输出结果如下图所示:
由上图可知,视图原点和场景原点重合了,若对代码做如下修改:
scene->setSceneRect(-200, -200, 400, 400);
// -200是相对于场景中心位置的偏移,由于是在X轴和Y轴的反方向,故为负数
输出结果如下图所示:
由上图可知,场景的原点在视图的中心位置。若对代码做如下修改:
scene->setSceneRect(-400, -400, 400, 400);
输出结果如下图所示:
由上图可知,场景的原点在视图的右下角位置。
从这三次的实验结果来看,最后一条打印的结果是一样的,也就是说场景的左上角一直和视图的左上角重合,当然也有可能出现不重合的情况。
三、图元(QGraphicsItem)坐标
图元使用自己的本地坐标,这个坐标系统通常以图元中心为原点,这也是所有变换的原点。图元坐标X轴正方向向右,Y轴正方向向下。图元创建后,只需注意图元坐标就可以了,QGraphicsScene和QGraphicsView会完成所有的变换。图元坐标如下图所示:
当然在自定义图元时,也可以指定图元的原点为其他位置,分析下面代码:
butterfly.h
#ifndef BUTTERFLY_H
#define BUTTERFLY_H
#include <QObject>
#include <QGraphicsItem>
#include <QPainter>
#include <QGraphicsScene>
#include <QGraphicsView>
class Butterfly : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Butterfly(QObject *parent = 0);
QRectF boundingRect() const;
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *);
private:
QPixmap pix_up; //用于表示两幅蝴蝶的图片
QPixmap pix_down;
};
#endif // BUTTERFLY_H
butterfly.cpp
#include "butterfly.h"
#include <math.h>
#include <QDebug>
Butterfly::Butterfly(QObject *parent) : QObject(parent)
{
pix_up.load(":/img/up.png");
pix_down.load(":/img/down.png");
}
QRectF Butterfly::boundingRect() const
{
return QRectF(-pix_up.width()/2, -pix_up.height()/2, pix_up.width(), pix_up.height());
}
void Butterfly::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
painter->drawPixmap(boundingRect().topLeft(), pix_up);
}
上述代码中,函数QRectF Butterfly::boundingRect() const
为图元限定了区域范围(图元左上角坐标以及宽和高),上述实现中图元的原点便在图元的中心,若改为如下实现:
QRectF Butterfly::boundingRect() const
{
return QRectF(0, 0, pix_up.width(), pix_up.height());
}
则,原点是图元的左上角,如下图所示:
下面代码是添加图元到场景中:
Butterfly *butterfly = new Butterfly();
butterfly->setPos(scene->sceneRect().left(), scene->sceneRect().top());
其中butterfly->setPos(scene->sceneRect().left(), scene->sceneRect().top());
指定***图元的原点在场景中的坐标***,若图元的原点在左上角,那么根据这段代码,可知图元在场景中的坐标如下图所示:
若setPos函数如下调用:
butterfly->setPos(scene->sceneRect().left()+100, scene->sceneRect().top()+100);
则坐标图便如下所示:
四、运行结果
下图为本次实验最终运行结果: