原文地址:http://devbean.blog.51cto.com/448512/235332
此后讲解内容为QT的2D绘图
一 基本概念
1.
Qt的绘图系统允许使用相同的API在屏幕和打印设备上进行绘制。
整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。
QPainter:用来执行绘制的操作;
QPaintDevice是一个二维空间的抽象,这个二维空间可以由QPainter在上面进行绘制;
QPaintEngine提供了画笔painter在不同的设备上进行绘制的统一的接口。QPaintEngine类用在QPainter和QPaintDevice之间,并且通常对开发人员是透明的,除非你需要自定义一个设备,这时候你就必须重新定义QPaintEngine了。
2. QPainter QPaintDevice QPaintEngine
三者之间的关系如下图所示
这种关系的优点:
由于所有的绘制都遵循着同一种绘制流程,
(1)可以很方便的添加新的特性
(2)为不支持的功能添加一个默认的实现方式。
3. QtOpenGL模块
Qt提供了一个独立的QtOpenGL模块
(1)与其他组件的相同之处:可以让你在Qt的应用程序中像使用其他的Qt组件一样使用OpenGL功能
(2)与其他组件的的不同之处:它使用OpenGL作为显示技术,使用OpenGL函数进行绘制
二 代码
1.步骤
Qt的绘图系统的实质:使用QPainter在QPainterDevice上面进行绘制,二者使用QPaintEngine进行通讯。
(1)步骤一:定义一个组件
class PaintedWidget : public QWidget
{
public:
PaintedWidget();
protected:
void paintEvent(QPaintEvent *event);
};
上段代码定义了一个构造函数,并且重定义paintEvent()函数。
void paintEvent(QPaintEvent *event);
由函数名称可知该函数是一个事件的回调函数。
一般而言,Qt的事件函数都是protected的,所以,如果你要重写事件,就需要继承这个类了。
(2)步骤二 增加构造函数内的代码
构造函数里面主要是一些大小之类的定义。
PaintedWidget::PaintedWidget()
{
resize(800, 600);
setWindowTitle(tr("Paint Demo"));
}
(3)步骤三 实现paintEvent()函数
void PaintedWidget::paintEvent(QPaintEvent *event)
{
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);
}
(4)步骤四.显示paintedWidget,并执行函数
main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
PaintedWidget w;
w.show();
return app.exec();
}
2.所有代码
(1)painter.pro
#-------------------------------------------------
#
# Project created by QtCreator 2017-03-24T21:59:09
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Painter
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += main.cpp\
paintedwidget.cpp
HEADERS += paintedwidget.h
INCLUDEPATH+=D:\InstallOpencv\opencvBinary\include\opencv\
D:\InstallOpencv\opencvBinary\include\opencv2\
D:\InstallOpencv\opencvBinary\include
LIBS+= D:\InstallOpencv\opencvBinary\lib\libopencv_bgsegm310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_bioinspired310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_calib3d310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_ccalib310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_core310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_cvv310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_datasets310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_dnn310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_dpm310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_face310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_features2d310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_flann310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_fuzzy310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_highgui310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_imgcodecs310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_imgproc310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_line_descriptor310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_ml310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_objdetect310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_phase_unwrapping310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_photo310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_plot310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_reg310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_rgbd310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_saliency310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_shape310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_stereo310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_stitching310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_structured_light310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_superres310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_surface_matching310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_text310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_tracking310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_video310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_videoio310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_videostab310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_xfeatures2d310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_xobjdetect310.dll.a\
D:\InstallOpencv\opencvBinary\lib\libopencv_xphoto310.dll.a
用于配置环境
(2)paintedWidget.h
#ifndef PAINTEDWIDGET_H
#define PAINTEDWIDGET_H
#include <QWidget>
class PaintedWidget : public QWidget
{
Q_OBJECT
public:
PaintedWidget(QWidget *parent = 0);
~PaintedWidget();
protected:
void paintEvent(QPaintEvent *event);
};
#endif // PAINTEDWIDGET_H
用于表示构造函数的结构
(3)paintedWidget.cpp
#include "paintedwidget.h"
#include<QPainter>
#include<QPaintDevice>
#include<QPaintEngine>
PaintedWidget::PaintedWidget(QWidget *parent)
: QWidget(parent)
{
resize(800, 600);
setWindowTitle(tr("Paint Demo"));
}
PaintedWidget::~PaintedWidget()
{
}
void PaintedWidget::paintEvent(QPaintEvent *event)
{
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);
}
用于实现构造函数
(4)main.cpp
#include "paintedwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PaintedWidget w;
w.show();
return a.exec();
}
3.运行结果
三 知识点解释
1.
QPainter painter(this);
(1)这一行代码声名了一个Qpainter对象。
由于我们在这个函数的栈空间建立了对象,因此不需要delete。
(2)QPainter接收一个QPaintDevice*类型的参数。
QPaintDevice有很多子类,比如QImage和QWidget。
QPaintDevice可以理解成要在哪里去画,而现在我们希望在这个widget上画,因此传入的是this指针。
2.
//用于绘制直线
painter.drawLine(80, 100, 650, 500);
//用于绘制长方形
painter.drawRect(10, 10, 100, 400);
//用于绘制椭圆
painter.drawEllipse(50, 150, 400, 200);
QPainter有很多以draw开头的函数,用于各种图形的绘制。
所有的draw函数如下图所示
3.
painter.setPen(Qt::red);
painter.setPen(QPen(Qt::green, 5));
painter.setBrush(Qt::blue);
setPen用于设置画笔;setBrush用于设置画刷。
四 画笔 画刷
Qt绘图系统提供了三个主要的参数设置,画笔(pen)、画刷(brush)和字体(font)。
1. 画笔
(1)画笔是用于绘制线的,比如线段、轮廓线等。
画笔类即QPen,可以设置画笔的样式,画笔的颜色,画笔的转折点样式等。
(2)画笔的样式可以在创建时指定,也可以由setStyle()函数指定。
(3)画笔支持三种主要的样式:笔帽(cap),结合点(join)和线形 (line)。
样式图如下
图共分成三行:第一行是Cap样式,第二行是Join样式,第三行是Line样式。QPen允许你使用setCapStyle()、setJoinStyle()和setStyle()分别进行设置。
2.画刷
(1)作用:填充封闭的几何图形
(2)两个参数:颜色和样式。也可使用纹理或者渐变色来填充图形。
(3)不同的画刷样式
注意:这些样式也可用通过一个enum进行设置
3.OpenGL是一个状态机,含义是OpenGL保存的只是各种状态。
比如,你把颜色设置成红色,那么,直到你重新设置另外的颜色,它的颜色会一直是红色。
QPainter也是这样,它的状态不会自己恢复,除非你使用了各种set函数。因此,如果在上面的代码中,我们在椭圆绘制之后再画一个椭圆,它的样式还会是绿色5px的轮廓和蓝色的填充,除非你显式地调用了set进行更新。