使用QPainter绘图的时候首先要搞清楚的就是坐标系统,本文的目的就是理清楚各种坐标系。
· 物理坐标:绘图设备实际的坐标,以像素为单位。所谓的绘图设备就是继承QPaintDevice的类,例如QWidget。这个坐标系统是不变的,原点在左上角。见下图。
![](https://img-blog.csdnimg.cn/img_convert/9672a5d461d73fc0b56f09c112267398.png)
视口坐标:视口是可以自定义的任意一个矩形,它定义的坐标就是视口坐标。例如下面就是重新定义的一个视口。
![](https://img-blog.csdnimg.cn/img_convert/071fea4ade1c09eb3f5c8a160e4c9918.png)
窗口坐标:窗口坐标是逻辑坐标。
说了上面三个坐标,除了物理坐标比较明确,感觉视口和窗口的概念还是比较模糊?用实例说话。
首先明确一点,视口和窗口就是两个矩形,默认情况下,就是绘图设备的整个矩形区域。就是下面的红色框框。如果QWidget大小发生了变化,那么视口和窗口也会改变。在重写的paintEvent方法中,可以打印出来看看。
![](https://img-blog.csdnimg.cn/img_convert/8acfb822ebfb669572184c799b875163.png)
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
qDebug()<<painter.viewport();//视口
qDebug()<<painter.window();//窗口
}
我们现在自定义一个视口:
QPainter painter(this);
QRect rect(50,50,200,300);
painter.setViewport(rect);//自定义视口
自定义的这个视口就是一个矩形框,(50,50,200,300)是物理坐标(单位像素),也就是说这个视口的左上角的物理坐标是(50,50),它的大小是200*300。长这个样子:
![](https://img-blog.csdnimg.cn/img_convert/81dc1c72e6562a9e143c5820fe8d6646.png)
绿色的框是绘图设备,绿色的坐标是物理坐标(单位像素)。黑色的框就是自定义的视口(50,50,200,300)。
上面就是自定义的视口,窗口呢?假设这个时候绘图设备是800*600,那么窗口就是(0,0,800,600)。因为你没有重新定义窗口,窗口还是这样,它是默认值。这个默认值就是(0,0,800,600)。注意这个值(0,0,800,600)取决于绘图设备的大小,如果绘图设备变成了400*300的大小,窗口的这个值就变成了(0,0,400,300)。为什么要把“值”标黑呢?因为它仅仅是值。窗口也是一个矩形,这个矩形始终跟视口一致。上面视口重新定义了,窗口也跟着变。变成下面这个样子:
![](https://img-blog.csdnimg.cn/img_convert/c364c49538eba3e907de449495be404f.png)
上图绿色的是绘图设备,红色的是视口,蓝色的是窗口。一句话,视口长什么样,窗口就长什么样。可此时视口的值是(50,50,200,300),窗口是(0,0,800,600),什么意思呢?前者是物理坐标,后者是在定义逻辑坐标。首先知道窗口什么样子,就是上面的蓝色矩形,给它一个值(0,0,800,600),什么意思呢?就是在定义窗口坐标系(逻辑坐标)。这个坐标系长这样:
![](https://img-blog.csdnimg.cn/img_convert/7bcc59974345c2121fab5b7448a667fe.png)
(0,0,800,600)这个值就定义了窗口坐标系。(0,0)表示窗口左上角的逻辑坐标,(800,600)表示窗口右下角的逻辑坐标,有了这两个坐标,一个坐标系就定义了。后面的绘图都是基于这个窗口坐标系。注意,这个坐标系跟物理坐标里头的像素单位没有关系。
画一条起点在(0,0)终点在(800,600)的线:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QRect rect(50,50,200,300);
painter.setViewport(rect);//自定义视口
painter.drawLine(0,0,800,600);
}
![](https://img-blog.csdnimg.cn/img_convert/075b83465939b5e5c91f9805c449fd3f.png)
在这条线在坐标系上,长这样(就是下图的黑色斜线):
![](https://img-blog.csdnimg.cn/img_convert/62f890f1a93cf9508e11f8921d0ed7d7.png)
视口矩形决定了窗口矩形,窗口的值(0,0,800,600)决定了窗口坐标系。再说一边这个值(0,0,800,600)取决于绘图设备的大小,因为它是默认值。这里当然也可以改变窗口的这个值。
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QRect rect(50,50,200,300);
painter.setViewport(rect);//自定义视口
painter.setWindow(-1000,-1500,2000,3000);//自定义窗口
}
这时候窗口坐标系长这个样子:
![](https://img-blog.csdnimg.cn/img_convert/c496d307aecef37412bbd6e63fa585a8.png)
(-1000,-1500,2000,3000)这个值是说,窗口矩形中(红色或者蓝色的矩形),左上角的逻辑坐标是(-1000,-1500)右下角的坐标是(1000,1500),一般定义窗口坐标系都采用这种形式,因为很显然,它的原点在矩形的中心,而且x轴和y轴的刻度一样。
画一个线:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPen pen;
pen.setWidth(10);
painter.setPen(pen);
QRect rect(50,50,200,300);
painter.setViewport(rect);//自定义视口
painter.setWindow(-1000,-1500,2000,3000);//自定义窗口
painter.drawLine(0,0,1000,1500);
}
![](https://img-blog.csdnimg.cn/img_convert/a5149cdc7bd650171e32d07514b81dd3.png)
这根线在坐标系统中是这样的(下图黑色的斜线):
![](https://img-blog.csdnimg.cn/img_convert/13481da07dd91fbe0db08e34c96ae12f.png)