赞
踩
一、基础概念:
在QPainter的默认坐标系中,点(0,0)位于绘图设备的左上角,x坐标向右增长,y坐标向下增长。默认坐标系的每个像素占1 x 1大小的区域。
理论上,像素的中心取决于半像素坐标。例如,窗口部件的左上角像素覆盖了点(0,0)到点(1,1)的区域,它的中心在(0.5,0.5)位置。
视口和窗口密不可分。视口是物理坐标系下指定的任意矩形。窗口和视口是同一个矩形,但是窗口是逻辑坐标系,窗口可以定义视口的逻辑坐标范围。
默认情况下,视口和窗口都设置设备的矩形。例如,如果设备是300 x 300的矩形,视口和窗口都是左上角为(0,0)的300 x 300 的相同矩形,此时逻辑坐标系和物理坐标系一致。
例如在逻辑坐标系下绘制一个左上角为(0,0)的100 x 100 的矩形,如下所示:
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
- setPalette(QPalette(Qt::white));
- setAutoFillBackground(true);
- this->resize(300 , 300 ); // 设备坐标(物理坐标)
- }
- void Widget::paintEvent(QPaintEvent *event)
- {
- Q_UNUSED(event);
- QPainter painter(this);
-
- //设置画笔
- QPen pen;
- pen.setWidthF(1); //线宽
- pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
- pen.setCapStyle(Qt::FlatCap);//线端点样式
- pen.setJoinStyle(Qt::BevelJoin);//线的连接点样式
- pen.setColor(Qt::gray); //划线颜色
-
- pen.setColor(Qt::red); //划线颜色
- painter.setPen(pen);
-
- painter.drawText(QPoint(width() / 2, 10), QString("widget size (%1, %2)")
- .arg(width()).arg(height()));
-
- pen.setColor(Qt::blue); //划线颜色
- painter.setPen(pen);
- painter.drawRect(0, 0, 100, 100);
- }
由上图可知,逻辑坐标系和物理坐标系一致的。
二、视口与窗口:
QPainter提供了视口(Viewport)和窗口(Window)两个坐标系,通过QPainter内部的坐标变换矩阵自动转换为绘图设备的物理坐标。
视口表示绘图设备(例如QImage, QPicture, QPixmap, QWidget等)的任意一个矩形区域的物理坐标,可以只选取物理坐标的一个矩形区域用于绘图。默认情况下,视口(Viewport)等于绘图设备的整个矩形区,属于物理坐标系。
视口矩形区域通过painter.setViewport(rect)方法设置,然后通过通过painter.setWindow()方法设定这个矩形区域的范围,配合使用,否则会出现问题(下文会举例写到)。
举例:在窗体部件(绘图设备)里取一块矩形(具体见代码)作为视口,同时设置视口矩形区域的范围(-100, -100, 200, 200),即左上角为(-100,-100),右下角为(100,100)。通过QPainter绘制一个左上角为(0,0),边长为100的正方形,如下所示:
- void Widget::paintEvent(QPaintEvent *event)
- {
- Q_UNUSED(event);
- QPainter painter(this);
-
- //设置画笔
- QPen pen;
- pen.setWidthF(1); //线宽
- pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
- pen.setCapStyle(Qt::FlatCap);//线端点样式
- pen.setJoinStyle(Qt::BevelJoin);//线的连接点样式
- pen.setColor(Qt::gray); //划线颜色
- painter.setRenderHint(QPainter::Antialiasing);
-
- pen.setColor(Qt::red); //划线颜色
- painter.setPen(pen);
-
- int W = width();
- int H = height();
-
- painter.drawText(QPoint(width() / 2 - 10, 10), QString("widget size (%1, %2)")
- .arg(W).arg(H));
-
- int side = qMin(W, H);//去长和宽的小值
- // viewport矩形区
- QRect rect((W - side) / 2 + 100, (H - side) / 2 + 100, side - 200, side - 200);
- // 在原有坐标系下,绘制出Viewport区域
- painter.drawRect(rect);
- painter.drawText(QPoint(width()/2 - 50, 50), QString("rect size (%1, %2)")
- .arg(rect.width()).arg(rect.height()));
-
- painter.setViewport(rect);//设置 Viewport
- painter.setWindow(-100, -100, 200, 200); // 设置窗口范围,逻辑坐标
-
- // 绘制矩形中心十字线
- pen.setColor(Qt::gray);
- pen.setStyle(Qt::DashLine);
- painter.setPen(pen);
- painter.drawLine(QPoint(-100, 0), QPoint(100, 0));
- painter.drawLine(QPoint(0, -100), QPoint(0, 100));
-
- pen.setColor(Qt::blue); //划线颜色
- pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
- painter.setPen(pen);
- painter.drawRect(0, 0, 100, 100);
- }
在上述代码中,如果未设置painter.setWindow()方法,即没有设定视口矩形的范围,系统将默认把绘图设备的区域,与视口矩形进行绑定。如果绘图设备是矩形的话,绘制的蓝色矩形将是个矩形,如果把绘图设备区域拉宽的话,蓝色矩形将被收窄。坐标原点都是左上角。
如果将painter.setWindow(-100, -100, 200, 200)的范围,改成(-200, -200, 400, 400),蓝色的矩形将缩小一倍。
三、逻辑坐标向物理坐标的转换:
由上面的例子,可以总结出转换规律:
默认情况视口和窗口坐标一致;如果设置视口矩形,窗口也要保证矩形一致,但需要通过setWindow方法设置矩形的逻辑坐标范围。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。