前言
QWidget、QPixmap以及QImage是绘图设备,使用painter可在上面绘图,绘图设备使用物理坐标系,左上角为(0,0),可设置视口决定在哪里显示绘图,物理坐标系的负坐标轴部分不能显示。
painter->drawRect()等传入的是逻辑坐标,默认逻辑坐标系的原点和物理坐标系重合,逻辑坐标系可以平移、旋转、缩放等坐标系变换,平移可以移动坐标系,逻辑坐标系的负坐标轴区域也可以用于绘图。设置setViewport()决定了要显示逻辑坐标系中的哪部分区域,传入的参数为逻辑坐标。
窗口与视口的解析在上篇博客中已记录不再详述,本篇博客主要记录在QGraphicsItem::paint()中绘图,重点在QGraphicsItem的坐标和绘图的坐标系的关系。在绘图时总是参考Item的位置来绘图,或者绘制在Item内部或者外部等,因此区分paint绘制的坐标系和item的局部坐标系很重要。
paint坐标系和item坐标系
QGraphicsItem的坐标系
在QGraphics体系中,Item自身存在局部坐标系,通过item->setRect(x,y,w,h)可设置item在局部坐标系中的位置和大小,通过setPos(x,y)可设置item的局部坐标系原点在父坐标系中的位置。具体的关系如下图所示:
因此item在父类坐标系中的绝对位置是由pos和rect决定的。在使用时,常常将item的局部坐标转移到pos上,这样更利于操作。计算在父类坐标系中的位置时可以如此获取:
item->mapToParent(item->rect());
//或者
setPos(rect.x(), rect.y());
setRect(0,0,rect.width(),rect.height());
QGraphicsItem::paint绘制的坐标系
QgraphicsItem::paint类似于QWidget::paintEvent。函数原型如下所示:
C++ void QGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
QPainter绘图坐标系的原点默认在Item::pos()处,x轴向右,y轴向下,与Item的局部坐标系重合。绘图坐标系可通过painter->translate(offset)
实现坐标系的平移。
绘图坐标系可使用translate
rotate
scale
实现坐标系变换,使用时需要注意的是:translate移动的是坐标系原点,rotate是坐标系原点不动,旋转绘图坐标系,scale是坐标系原点不动,缩放绘图坐标系。旋转和缩放常常需要使用平移先移动坐标系,保证坐标原点处的位置不会随着旋转或者缩放而移动位置,这主要是为了确保绘制的图形或者文字在预想的区域(如矩形内)。
缩放。缩放时,从x或者y方向上看,坐标系原点不动,而其余的点则远离或者靠近原点,坐标原点不动指的是绘图坐标系的原点在Item中的位置不动。在使用时,如果矩形不在局部坐标系的原点处,可以先将坐标系移动到矩形的左上角,而后执行缩放。由于坐标系已经发生了移动,最后绘制文字时文字的坐标就需要设置为(0,0),而文字的尺寸应该设置为文字缩放前的宽度和高度。
painter->translate(30,20);//将painter的逻辑坐标系移动到矩形所在的位置
painter->scale(sx,sy);//缩放逻辑坐标系
painter->drawText(QRect(0,0,textWidth,textHeight), text, Qt::AlignLeft|Qt::AlignTop);//坐标系发生变化,因此文字的绘制区域也要变
或者可先将坐标系移动到矩形左上角,执行缩放,而后再移动回去,最后绘制文字。这样做可以接着之前的内容进行绘制,只不过在绘制文字的时候,绘制坐标要变为矩形的左上角点的位置。在将坐标系移动回去后,坐标系的所有点中,只有缩放时的坐标原点(现在的(30,20)点)相对于Item的相对位置没有改变。
painter->translate(30,20);//将painter的逻辑坐标系移动到矩形所在的位置
painter->scale(sx,sy);//缩放逻辑坐标系
painter->translate(-30,-20);//将painter的逻辑坐标系移动原位
painter->drawText(QRect(30,20,textWidth,textHeight), text, Qt::AlignLeft|Qt::AlignTop);//坐标系发生变化,因此文字的绘制区域也要变
旋转。旋转时,坐标系原点相对于Item的位置不动,其余点发生旋转。因此若要以矩形的中心点旋转文字,则先将坐标系移动到矩形中心点,在绘制文字时将文字的中心与坐标系原点重合,并且设置为居中绘制即可。
painter->drawLine(0, 0, 100, 0);//绘制坐标系
painter->drawText(100, -2, "x");
painter->drawLine(0, 0, 0, 100);
painter->drawText(-2, 100, "y");
painter->translate(curRect.center());//将绘制坐标系移动到矩形中央
painter->rotate(90);//旋转90度
painter->setPen(Qt::red);//绘制坐标系
painter->drawLine(0, 0, 100, 0);
painter->drawText(100, -2, "x");
painter->drawLine(0, 0, 0, 100);
painter->drawText(-2, 100, "y");
painter->drawText(QRectF(-50, -50, 100, 100), Qt::AlignCenter,"未定义");//绘制文字
绘制常用函数
- save()和restore()
用于保存和恢复painter当前的坐标变换以及设置的颜色属性等。有时候为绘制比较复杂图形使用了坐标变换,而绘制完成后需要恢复最初的状态接着绘制下一个图形,此时就有必要使用save和restore了。