目录
前言
没用的文章千篇一律,我们的目标是不浪费读者时间,与读者一起成长进步~
一、关于GraphicsView、GraphicsScene和GraphicsItem三个坐标系的建立
首先,对于网上千篇一律关于GraphicsView、GraphicsScene和GraphicsItem坐标系的描述这里就不在赘述了,这里想要说明在实际应用中如何去建立这三个坐标系的对应关系来更方便地操控图形项。
1、GraphicsView的坐标原点(0,0)是在视图View的左上角,GraphicsScene的坐标原点(0,0)是在场景Scene的中心位置,即矩形/正方形的中心,场景Scene的左上角坐标是负值,其坐标值为场景Scene矩形宽和高的一半。GraphicsItem即图形项的坐标原点(0,0)一般是图形项的中心位置,默认场景原点与图形原点重合,但是我添加的图片的坐标原点是图片的左上角,不知道为什么~~~
2、对于如何设置这三个坐标系这里有几点建议:
①.尽量保证视图View的尺寸大于等于场景Scene的尺寸,因为这样可以把场景Scene中的图形项全部显示在视图View中;
②.在设置场景矩形rect时,尽量把场景矩形rect的左上角坐标设置成(0,0),长宽设置成与视图View长宽相等,这样就相当于把场景Scene的坐标原点(0,0)转移至左上角,与视图View坐标系的原点(0,0)重合,至于为什么要这么做,这里我踩过很多坑 - - 。例如设置图形项旋转中心时,如果以场景Scene默认的坐标原点设置,那么设置的旋转中心位置大概率跟你想的位置有偏差,这里亲自试一下就知道了,这只是其中一个坑,后面还会有很多坑要踩~~~
③.使用setPos(x,y)函数设置Item图形项的坐标时,该坐标是基于场景Scene的坐标原点的。
二、如何使用背景网格?
1.使用drawBackground函数
首先我们需要新建一个继承自QGraphicsScene的子类DrawBackGroud,然后在DrawBackGroud.h中声明虚函数drawBackground函数:
virtual void drawBackground(QPainter *painter, const QRectF &rect);
在DrawBackGroud.cpp中重写实现drawBackground函数:
//该函数在创建Scene的时候会自动调用
void DrawBackGroud::drawBackground(QPainter *painter, const QRectF &rect)
{
Q_UNUSED(rect);
/*设置画笔属性*/
QPen pen;
pen.setColor(QColor(60,60,60));
pen.setWidth(2);
painter->setPen(pen);
right = Global_param::View_right-2; //这里视图View的宽和高是QRect类型
bottom = Global_param::View_bottom-2;
//绘制y方向网格,这里每间隔50个像素点绘制一次
for(int i=1; i<=bottom+1; i = i+50)
{
painter->drawLine(0, i, right+2, i);
}
//绘制x方向网格,这里每间隔50个像素点绘制一次
for(int i=1; i<=right+1; i = i+50)
{
painter->drawLine(i, 0, i, bottom+2);
}
update();
}
2.绘制背景网格需要避的坑
注意:由于drawBackground函数的其中一个参数rect为暴露矩形,这个参数会随着场景中图形项的改变,场景矩形的改变,还有一些其他东西的改变而改变,因此使用这个参数作为标准进行绘制背景网格很容易出问题,这里建议使用全局变量,详细说明如下:
①、将视图View的尺寸及对应坐标赋值给全局变量,方便在其他类中使用;
②、在绘制背景网格时使用视图View的尺寸进行绘制,这样可以保证绘制的网格不会随意变动,而且网格可以填满View。
③、当场景有任何改变时drawBackground函数都会自动调用,如果使用默认的视口更新模式,当移动或者旋转场景中的图形项时,背景网格很容易被破坏掉,这里推荐使用如下视口更新模式:
ui->View->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); //设置视图更新模式,如果使用默认更新模式(最小更新模式),则改变Item状态,背景网格会被破坏
这里的ui->View为我设置的视图View,大家可根据自己的代码进行相应调整。
这里还需要注意的是,当放缩整个视图View时,背景网格也会跟着一起被放缩,如果此时想让背景网格大小保持不变,有几种思路:
1、 根据视图View的放缩倍数scale,在绘制背景网格时按照1/scale进行绘制,这种方法我再使用时有些小问题,大家可以试一下~
2、新建label组件,设置label组件与视图View的大小和坐标重合,然后把网格图片添加到label组件中,把label组件设置为放到视图View图层的后面一层,关键一步,把视图View的背景设置成透明即可显示label中的网格,亲测有效!!!
ui->View->setStyleSheet("background:transparent"); //设置顶层背景透明,即把View放在label上层,将View背景设置为透明,即可显示下面的label网格
总结
以上是我在使用GraphicsView框架时踩的一些小坑,希望大家不要踩我踩过的坑~
第一次写博客没什么经验,写的也比较差,希望大家在看的时候多多包涵~~~后续如果有时间还会继续更新关于GraphicsView的一些内容,See you~