Qt中提供了强大的2D绘图系统,可以使用相同的API在屏幕和绘图设备上进行绘制,它主要基于QPainter、QPaintDevice和QPaintEngine这三个类。
- QPainter用来执行绘图操作;
- QPaintDevice提供绘图设备,它是一个二维空间的抽象,可以使用QPainter在其上进行绘制;
- QPaintEngine提供了一些接口,可以用于QPainter在不同的设备上进行绘制。
为什么需要2D绘图?
一个定制化的完美产品,从来都不仅仅是利用库中现有的控件来完成,2D绘图给我们提供了专用定制化的平台,这就是创意的开始。 QPaintDevice是一个绘制设备。 是一个二维空间的抽象, 是所有可以绘制对象的基类, 包括QWidget QPicture QPrinter等。
QPainter能干什么?
QPainter提供高度优化的功能来完成大多数绘图GUI程序的要求。它可以绘制从简单的线条到复杂的形状,如线和弦。它也可以绘制对齐的文本和像素图片。通常情况下是在一个常规坐标系中进行绘制,但也可以进行窗口——视口变换。QPainter可以在任何继承了QPaintDevice类的对象上运行。
可以把QPainter想象成一个画笔,开发人员拿着画笔理论上是可以绘制任何你想要的图形,前提是你绘画功底足够(逻辑+算法)。
QPainter怎么用?
QPainter 一般在一个部件(widget)重绘事件( PaintEvent )的处理函数paintEvent ()中进行绘制,首先要创建QPainter 对象(画笔),然后进行图形的绘制, 最后销毁QPainter 对象。
QPainter的核心功能是绘图,但该类还提供了几个功能,允许您自定义QPainter的设置及其渲染质量。另外,通过指定QPainter的构图模式,您可以控制如何将不同的形状合并在一起。
在QPainter中提供了一些方便的函数来绘制常用的图形,而且还可以设置线条和边框的画笔以及进行填充的画刷。
例如绘制一条直线:
在widget.h文件中声明重绘事件处理函数:
protected:
void paintEvent(QPaintEvent *event);
在widget.cpp文件中对paintEvent()函数进行如下定义:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawLine(QPoint(0, 0), QPoint(100, 100));
}
这里指定了this为绘图设备,即表明在该部件上进行绘制。使用这个构造函数创建的对象会立即开始在设备上进行绘制,它会自动调用begin()函数,然后在QPainter的析构函数中调用end()函数结束绘制。如果在构建QPainter对象时不想指定绘制设备,那么可以使用不带参数的构造函数:
QPainter painter;
painter.begin(this);
painter.drawLine(QPoint(0, 0), QPoint(100, 100));
painter.end();
drawLine()
该函数绘制了一条线段,这里使用了该函数的一种重载形式QPainter::drawLine ( const QPoint & p1, const QPoint & p2 )其中p1和p2分别是线段的起点和终点。这里的QPoint(0, 0)就是窗口的原点,默认是窗口的左上角(不包含标题栏)。
QPainter中常用图形绘制函数介绍
函数 | 功能 |
drawArc() | 绘制圆弧 |
drawChord() | 绘制弦 |
drawConvexPolygon() | 绘制凸多边形 |
drawEllipse() | 绘制椭圆 |
drawLine() | 绘制线条 |
drawPie() | 绘制扇形 |
drawPoint() | 绘制点 |
drawPolygon() | 绘制多边形 |
drawPolyline() | 绘制折线 |
drawRect() | 绘制矩形 |
drawRoundedRect() | 绘制圆角矩形 |
drawArc()——弧(演示[0])
drawChord()—— 弦
drawConvexPolygon()—— 凸多边形
drawEllipse()——椭圆
drawImage()—— QImage表示的图像
drawLine()——线(演示[0] )
drawLines()—— 多条线
drawPath()——路径
drawPicture()—— 按QPainter指令绘制
drawPie()——扇形
drawPixmap()——QPixmap表示的图像
drawPoint()—— 点
drawPoints()——多个点
drawPolygon()——多边形
drawPolyline()——多折线
drawRect()—— 矩形(演示[0])
drawRects()—— 多个矩形
drawRoundRect()——圆角矩形
drawText()—— 文字
drawTiledPixmap()—— 平铺图像
drawLineSegments()—— 绘制折线
QPainter—设置画笔(QPen)
QPen定义了用于QPainter应该怎样画线或者轮廓线。画笔具有样式style() 、宽度width() 、画刷brush() 、笔帽样式capStyle()和连接样式joinStyle()等属性。
- 画笔的样式style()定义了线的样式。
- 画刷brush()用于填充画笔所绘制的线条。
- 笔帽样式capStyle()定义了使用QPainter绘制的线的末端;
- 连接样式joinStyle()则定义了两条线如何连接起来。
- 画笔宽度width()或widthF()定义了画笔的宽。注意,不存在宽度为 0 的线。假设你设置 width 为 0,QPainter依然会绘制出一条线,而这个线的宽度为 1 像素。也就是说,画笔宽度通常至少是 1 像素。
这么多参数既可以在构造时指定,也可以使用 set 函数指定,完全取决于你的习惯。使用setWidth(),setBrush(),setCapStyle()和setJoinStyle()函数可以轻松修改各种设置(注意画笔的笔必须在更改笔的属性时重置)。
画笔风格
画笔端点风格
其中Qt::SquareCap风格表示线条的终点为方形,并且向前延伸了线宽的一半的长度;而Qt::FlatCap风格也是方形端点,但并没有延长;使用Qt::RoundCap风格的线条是圆形的端点,这些风格对宽度为0的线条没有作用。
画笔连接风格
其中Qt::BeveJoin风格填充了两个线条之间的空缺三角形;而Qt::RoundJoin是使用圆弧来填充这个三角形,这样显得更圆滑;使用Qt::MiterJoin风格,是将两个线条的外部边线进行扩展而相交,然后填充形成的三角形区域。这三种风格对于宽度为0的线条没有作用。
QPainter::drawArc ( const QRectF & rectangle, int startAngle, int spanAngle )
这里的三个参数分别对应于需要指定弧线所在的矩形、起始角度和跨越角度。
使用画刷
// 创建画刷
QBrush brush(QColor(0, 0, 255), Qt::Dense4Pattern);
// 使用画刷
painter.setBrush(brush);
// 绘制椭圆
painter.drawEllipse(220, 20, 50, 50);
// 设置纹理
brush.setTexture(QPixmap("image.png"));
// 重新使用画刷
painter.setBrush(brush);
// 定义四个点
static const QPointF points[4] = {
QPointF(270.0, 80.0),
QPointF(290.0, 10.0),
QPointF(350.0, 30.0),
QPointF(390.0, 70.0)
};
// 使用四个点绘制多边形
painter.drawPolygon(points, 4);
运行结果:
QPainter—设置画刷(QBrush)
QBrush 类提供了画刷来对图形进行填充, 一个画刷具有
- 样式(style)
- 颜色(color)
- 渐变( gradient )
- 文理(texture)
QBrush样式()使用Qt :: BrushStyle枚举定义填充模式。默认的风格是Qt :: NoBrush(取决于你如何构建画笔),不填充形状。标准的填充风格是Qt :: SolidPattern。设置画刷的方式有两种,一种是利用构造函数,另外一种是利用setstyle函数。
在Qt中使用的颜色一般都由QColor类来表示,它支持RGB、HSV和CMYK等颜色模型。QColor还支持基于alpha的轮廓和填充(实现透明效果),而且QColor类与平台和设备无关(颜色使用QColormap类向硬件进行映射)。在Qt中还提供了20种预定义的颜色,比如我们以前经常使用的Qt::red等 。
填充模式使用Qt::BrushStyle枚举变量来定义,包含了基本模式填充、渐变填充和纹理填充。
笔刷颜色(color)定义了填充图案的颜色。颜色可以是Qt的预定义颜色之一,Qt :: GlobalColor或任何其他自定义QColor。可以分别使用color()和setColor()函数获取和更改当前设置的颜色。
渐变填充
QGradient类就是用来和QBrush一起指定渐变填充的。Qt现在支持三种类型的渐变填充:
- 线性渐变(linear gradient)在开始点和结束点之间插入颜色;
- 辐射渐变(radial gradient)在焦点和环绕它的圆环间插入颜色;
- 锥形渐变(Conical)在圆心周围插入颜色。
这三种渐变分别由QGradient的三个子类来表示,QLinearGradient表示线性渐变,QRadialGradient表示辐射渐变,QConicalGradient表示锥形渐变。
线性渐变
QLinearGradient::QLinearGradient ( const QPointF & start, const QPointF & finalStop )
辐射渐变
QRadialGradient::QRadialGradient ( const QPointF & center, qreal radius, const QPointF & focalPoint )
锥形渐变
QConicalGradient::QConicalGradient ( const QPointF & center, qreal angle )
需要指定中心点center和一个角度angle(其值在0到360之间),然后沿逆时针从给定的角度开始环绕中心点插入颜色。这里给定的角度沿逆时针方向开始的位置为0,旋转一圈后为1。
示例:
// 线性渐变
QLinearGradient linearGradient(QPointF(40, 190), QPointF(70, 190));
// 插入颜色
linearGradient.setColorAt(0, Qt::yellow);
linearGradient.setColorAt(0.5, Qt::red);
linearGradient.setColorAt(1, Qt::green);
// 指定渐变区域以外的区域的扩散方式
linearGradient.setSpread(QGradient::RepeatSpread);
// 使用渐变作为画刷
painter.setBrush(linearGradient);
painter.drawRect(10, 170, 90, 40);