QPainter绘图系统

QPainter 和 QPaintDevice

Qt 的绘图系统使用户可以在屏幕或打印设备上用相同的 API 绘图,绘图系统基于 QPainter、QPaintDevice 和 QPaintEngine 类。QPainter 是用来进行绘图操作的类,QPaintDevice 是一个可以使用 QPainter 进行绘图的抽象的二维界面,QPaintEngine 给 QPainter 提供在不同设备上绘图的接口。QPaintENgine 类由 QPainter 和 QPaintDevice 内部使用,应用程序一般无需和 QPaintEngine 打交道,除非要创建自己的设备类型。一般的绘图设备包括 QWidget、QPixmap、QImage 等,这些绘图设备为 QPainter 提供一个“画布”。

paintEvent 事件和绘图区

QWidget 类及其子类时最常用的绘图设备,从 QWidget 类继承的类都有 paintEvent() 事件,要在设备上绘图,只需要重定义此事件并编写响应代码。创建一个 QPainter 对象获取绘图设备的接口,然后就可以在绘图设备的“画布”上绘图了。
paintEvent() 事件里绘图的基本程序结构是:

  • 01
  • 02
  • 03
  • 04
  • 05
void widget::paintEvent(QPaintEvent* event) { QPainter painter(this); // 创建与绘图设备关联的QPainter对象 // painter 在设备的窗口上绘图 }

QPainter 绘图的主要属性

用 QPainter 在绘图设备上绘图,主要是绘制一些基本的图形元素,包括点、直线、圆形、矩形、曲线、文字等,控制这些绘图元素特性的主要是 QPainter 的 3 个属性,分别如下:

  • pen 属性:是一个 QPen 对象,用于控制线条的颜色、宽度、线型等,上图的矩形边框的线条的特性就是由 pen 属性决定的。
  • brush 属性:是一个 QBrush 对象,用于设置一个区域的填充特性,可以设置填充颜色、填充方式、渐变特性等,还可以采用图片做材质填充。
  • font 属性:是一个 QFont 对象,用于绘制文字时,设置文字的字体样式、大小等属性。

使用这三个属性基本就控制了绘图的基本特点,当然还有一些其他的功能结合使用,比如叠加模式、旋转和缩放等功能。

创建实例

为了演示 QPainter 绘图的基本功能,创建一个 Qt Widget Application 项目,并选择窗口基类为 QWidget,自动创建窗体。创建后的项目有一个 Widget 类,为了简化代码功能,Widget 窗口里不放置任何其他组件,只用来绘图。
下面是 Widget 类的完整定义。只是重新定义了 paintEvent() 事件,在此事件里编写绘图代码。Q_DECL_OVERRIDE 宏表示这个函数时用父类虚函数的重载。

  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09
  • 10
  • 11
  • 12
  • 13
  • 14
class Widget : public QWidget { Q_OBJECT protected: void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; };

下面是 Widget 类构造函数和 paintEvent() 函数的代码,在界面上绘制如上图所示的一个填充矩形,演示了 QPainter 绘图的基本过程。

  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); setPalette(QPalette(Qt::white));//设置窗口为白色背景 setAutoFillBackground(true); } void Widget::paintEvent(QPaintEvent* event) { QPainter painter(this);//创建QPainter对象 painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); int W=this->width(); //绘图区宽度 int H=this->height(); //绘图区高度 //设置画笔 QPen pen; pen.setWidth(3); //线宽 pen.setColor(Qt::black); //划线颜色 //Qt::NoPen,Qt::SolidLine, Qt::DashLine, Qt::DotLine,Qt::DashDotLine,Qt::DashDotDotLine,Qt::CustomDashLine pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等 //Qt::FlatCap, Qt::SquareCap,Qt::RoundCap pen.setCapStyle(Qt::FlatCap);//线端点样式 //Qt::MiterJoin,Qt::BevelJoin,Qt::RoundJoin,Qt::SvgMiterJoin pen.setJoinStyle(Qt::BevelJoin);//线的连接点样式 painter.setPen(pen); QBrush brush; brush.setColor(Qt::yellow); brush.setStyle(Qt::SolidPattern); painter.setBrush(brush); painter.drawRect(rect); }

paintEvent() 函数中,首先创建与 Widget 关联的 QPainter 对象 painter,这样就可以用这个 painter 在 Widget 上绘图了。

QPen 的主要功能

QPen 用于绘图时对线条进行设置,主要包括线宽、颜色、线型等,主要接口如下:

| 函数原型 | 功能 |
| —————————————— | ——————————— |
| void setColor (QColor& color) | 设置画笔颜色、即线条颜色 |
| void setWidth (int width) | 设置线条宽度 |
| void setStyle (Qt::PenStyle style) | 设置线条样式,参数为 Qt::PenStyle 枚举类型 |
| void setCapStyle (Qt::PenCapStyle style) | 设置线条端点样式,参数为 Qt::PenCapStyle 枚举类型 |
| void setJoinStyle (Qt::PenJoinStyle style) | 设置连接样式,参数为 Qt::PenJoinStyle 枚举类型 |

线条样式

除了几种基本的线条样式,用户还可以自定义线条样式,自定义线条样式时需要用到 setDashOffet()setDashPattern() 函数。

线条端点样式

线条连接样式

QBrush 主要功能

QBrush 定义了 QPainter 绘图时的填充特性,包括填充颜色、填充样式、材质填充时的材质图片等,主要函数如下:

| 函数原型 | 功能 |
| ———————————— | ———————— |
| void setColor (QColor& color) | 设置画刷颜色,实体填充时即为填充颜色 |
| void setStyle (Qt::BrushStyle style) | 设置画刷样式 |
| void setTexture (QPixmap& pixmap) | 设置一个 QPixmap 类型的图片作为画刷图片 |
| void setTextureImage (QImage& image) | 设置一个 QImage 类型图片为画刷 |

Qt::BrushStyle

下面是使用资源文件里的一个图片进行材质填充的示例程序,用材质图片填充一个矩形。

  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
void Widget::paintEvent(QPaintEvent* event) { QPainter painter(this); int w = this->width(); int h = this->height(); QRect rect(w/4, h/4, w/2, h/2); QPen pen; pen.setWidth(3); pen.setColor(Qt::read); pen.setStyle(Qt::SolidLine); painter.setPen(pen); QPixmap texturePixmap(":/image/texture.jpg"); QBrush brush; brush.setStyle(Qt::TexturePattern); brush.setTexture(texturePattern); painter.setBrush(brush); painter.drawRect(rect); }