本文大部分内容来自于Qt5.5.1的API文档。
Qt的绘图系统允许使用相同的API在屏幕和其他打印设备上进行绘制。整个绘图系统基于QPainter,QPaintDevice和QPaintEngine三个类。
QPainter用来执行绘制操作;QPaintDevice是一个二维空间抽象,这个二维空间允许QPainter在上面进行绘制,也就是QPainter的工作空间;QPaintEngine提供了画笔在不同的设备上进行绘制的统一借口。QPaintEngine类应用于QPainter和QPaintDevice,对于开发人员来说一般是透明的,除非你要自定义一个设备,否则不用关心QPaintEngine类。我们可以把QPainter理解成画笔,把QPaintDevice理解成绘制的画纸。QPaintEngine就是让不同的纸张、屏幕可以使用相同的画笔的类。
我们看一个例子:
//paintwidget.h
#ifndef PAINTWIDGET_H
#define PAINTWIDGET_H
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
class PaintWidget : public QWidget
{
Q_OBJECT
public:
PaintWidget(QWidget *parent = 0);
~PaintWidget();
private:
void paintEvent(QPaintEvent *);
};
#endif // PAINTWIDGET_H
//paintwidget.cpp
#include "paintwidget.h"
PaintWidget::PaintWidget(QWidget *parent)
: QWidget(parent)
{
resize(800, 600);
setWindowTitle("Paint Demo");
}
void PaintWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawLine(80, 100, 650, 500);
painter.setPen(Qt::red);
painter.drawRect(10, 10, 100, 400);
painter.setPen(QPen(Qt::green, 5));
painter.setBrush(Qt::blue);
painter.drawEllipse(50, 150, 400, 200);
painter.save();
}
PaintWidget::~PaintWidget()
{
}
//main.cpp
#include "paintwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PaintWidget w;
w.show();
return a.exec();
}
代码在paintEvent中创建了一个QPainter对象,每次运行paintEvent时都会创建一个QPainter,这样其实是有问题的,因为QPainter都会被设置。如果设置出现不一致,则会出现屏幕闪动。QPainter对象在需要多次调用不同设置的画笔时,可以使用save()将状态保存下来,后面再使用restore()恢复。一般可以把QPainter作为需要绘制的类的私有成员,这样方便调用。
paintEvent()是QWidget本身具有的一个virtual protected函数,所以我们可以在子类中重写这个函数。那么paintEvent()是什么时候被调用的呢?Qt文档中描述有三条:1)repaint()或者update()被调用的时候。这样我们可以主动更新界面。2)被其他界面挡住后又恢复过来的时候。比如我们windows中运行上面的代码,在被其他窗口覆盖时会运行一次,然后在此窗口被激活时又会运行一次。
QPainter有两个构造函数,
QPainter::QPainter()
QPainter::QPainter(QPaintDevice * device)
如果使用第一个方法构造,则需要在后面指定绘图设备,如:
void MyWidget::paintEvent(QPaintEvent *)
{
QPainter p;
p.begin(this);
p.drawLine(...); // drawing code
p.end();
}
QPainter可以画很多几何图形,一般都是调用以draw开头的函数,具体可以参考API。
QPainter在绘制时按照程序运行的顺序进行绘制,如果出现重叠,则后面绘制的会把前面的覆盖掉。
QPainter可以使用setPen指定画笔,它有三个重载:
void QPainter::setPen(const QPen & pen);
void QPainter::setPen(const QColor & color);
void QPainter::setPen(Qt::PenStyle style);
画笔的主要功能是勾勒轮廓线,如果要填充,则需要使用QBrush–画刷。
QBrush定义了QPainter的填充模式,具有样式、颜色、纹理等特性。画刷的style()定义了填充样式,可以使用Qt::BrushStyle枚举,默认是Qt::NoBrush。具体枚举有:
画刷的color()可以返回一个当前使用的颜色,setColor()可以设置颜色。画刷的gradient()定义了渐变填充。这个属性只有在填充样式是QLinearGradient, QConicalGradient, 和QRadialGradient或者是继承自QGradient的。如Qt提供的一个例子:
QRadialGradient gradient(50, 50, 50, 50, 50);
gradient.setColorAt(0, QColor::fromRgbF(0, 1, 0, 1));
gradient.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0));
QBrush brush(gradient);
当画刷样式是Qt::texturePattern时,texture()定义了用于填充的纹理。即使没有设置样式为Qt::texturePattern,当调用setTexture是,QBrush会自动将style()设置为Qt::texturePattern.