图形绘制 QPainter

来源:互联网 发布:美容美体教学饮软件 编辑:程序博客网 时间:2024/05/17 08:13

QPainter painter(this); // 会立即开始在设备上绘制,自动调用begin()函数,然后析构函数中调用end()函数结束绘制。
QPainter painter;// 不带参数时,可以在后面调用QPainter::begin(QPaintDevice *device)来指定绘制设置,然后用完再调用end()函数。

void Widget::paintEvent((QPaintEvent *event)  {          QPainter painter(this); //this为绘图设备,即表明在该部件上进行绘制          painter.drawLine(QPaint(0, 0), QPaint(100, 100));  }  //等价于void Widget::paintEvent((QPaintEvent *event)  {          QPainter painter;          painter.begin(this);          painter.drawLine(QPaint(0, 0), QPaint(100, 100));          painter.end();  }  

使用画刷

画刷可以设置颜色和填充模式

QBrush brush(QColor(0,0,255), Qt::Dense4Pattern);  painter.setBrush(brush);  

使用画笔

//参数为:画刷,线宽,画笔风格,画笔端点,画笔连接风格  QPen pen(Qt::green, 5, Qt::DotLine, Qt::RoundCap, Qt::RoundJoin);  painter.setPen(pen);  

QPainter 常用的画图方法,都是以 draw 开头,非常直观的列出了绘图函数和绘制出来的图形:
这里写图片描述

坐标系

数学中使用的坐标系是笛卡尔坐标系,X 轴正向向右,Y 轴正向向上。但是,QPainter 也有自己的坐标系,和笛卡尔坐标系有点不一样,原点在 widget 的左上角而不是正中心,X 轴正向向右,Y 轴正向向下。注意: 每个 widget 都有自己独立的坐标系。
这里写图片描述

QPainter是一个状态机

所谓状态机,就是说,QPainter保存的只是各种状态。怎么理解呢?比如,你把颜色设置成红色,那么,直到你重新设置另外的颜色,它的颜色会一直是红色。它的状态不会自己恢复,除非你使用了各种set函数。因此,如果在上面的代码中,我们在椭圆绘制之后再画一个椭圆,它的样式还会是绿色5px的轮廓和蓝色的填充,除非你显式地调用了set进行更新。这可能是绘图系统较多的实现方式,因为无论是OpenGL、QPainter还是Java2D,都是这样实现的。

画线 - drawLine()

void MainWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.drawLine(30, 30, 150, 150);}

画多线段 - drawLines()

给定 N 个点,第 1 和第 2 个点连成线,第 3 和第 4 个点连成线,……,N 个点练成 (N+1)/2 条线,如果 N 是奇数,第 N 个点和 (0,0) 连成线。

void MultipleLinesWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.setRenderHint(QPainter::Antialiasing);    painter.translate(20, 20);    static const QPointF points[4] = {        QPointF(0.0, 100.0),        QPointF(20.0, 0.0),        QPointF(100.0, 0.0),        QPointF(120.0, 100.0)    };    painter.drawLines(points, 2); // 4 个点连成 2 条线}

画折线- drawPolyline()

给定 N 个点,第 1 和第 2 个点连成线,第 2 和第 3 个点连成线,……,第 N-1 和第 N 个点连成线,N 个点共连成 N-1 条线。

void PolylineWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.setRenderHint(QPainter::Antialiasing);    painter.translate(20, 20);    static const QPointF points[4] = {        QPointF(0.0, 100.0),        QPointF(20.0, 0.0),        QPointF(100.0, 0.0),        QPointF(120.0, 100.0)    };    painter.drawPolyline(points, 4);}

画多边形 - drawPolygon()

给定 N 个点,第 1 和第 2 个点连成线,第 2 和第 3 个点连成线,……,第 N-1 和第 N 个点连成线,第 N 个点和第 1 个点连接成线形成一个封闭的多边形。
在我们学习OpenGL的时候,肯定听过这么一句话:OpenGL是一个状态机。所谓状态机,就是说,OpenGL保存的只是各种状态。怎么理解呢?比如,你把颜色设置成红色,那么,直到你重新设置另外的颜色,它的颜色会一直是红色。QPainter也是这样,它的状态不会自己恢复,除非你使用了各种set函数。因此,如果在上面的代码中,我们在椭圆绘制之后再画一个椭圆,它的样式还会是绿色5px的轮廓和蓝色的填充,除非你显式地调用了set进行更新。这可能是绘图系统较多的实现方式,因为无论是OpenGL、QPainter还是Java2D,都是这样实现的

drawPolygon() 和 drawPolyline() 很像,但是 drawPolygon() 画的是一个封闭的区域,可以填充颜色,而 drawPolyline() 画的是一些线段,即使它们连成一个封闭的区域也不能填充颜色。

void PolygonWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.setRenderHint(QPainter::Antialiasing);    painter.translate(20, 20);    static const QPointF points[4] = {        QPointF(0.0, 100.0),        QPointF(20.0, 0.0),        QPointF(100.0, 0.0),        QPointF(120.0, 100.0)    };    painter.setBrush(Qt::yellow);    painter.drawPolygon(points, 4);}

可以用 drawPolygon() 来画圆,其实本没有圆,正多边形的边多了,便成了圆,这正是计算机里绘制曲线的原理,插值逼近,在曲线上取 N 个点,点之间用线段连接起来,当 N 越大时,连接出来的图形就越平滑,越接近曲线。

void PolygonCircleWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.setRenderHint(QPainter::Antialiasing); // 启用抗锯齿效果    painter.translate(width() / 2, height() / 2); // 把坐标原点移动到 widget 的中心    painter.setBrush(Qt::lightGray);    const int COUNT  = 10;  // 边数,越大就越像圆    const int RADIUS = 100; // 圆的半径    QPointF points[COUNT];  // 顶点数组    for (int i = 0; i < COUNT; ++i) {        float radians = 2 * M_PI / COUNT * i; // M_PI 是 QtMath 里定义的,就是 PI        float x = RADIUS * qCos(radians);        float y = RADIUS * qSin(radians);        points[i] = QPointF(x, y);    }    painter.drawPolygon(points, COUNT);}

画矩形 - drawRect()

void MainWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.setRenderHint(QPainter::Antialiasing);    painter.translate(30, 30);    int x = 0;    int y = 0;    int w = 100;    int h = 100;    painter.drawRect(x, y, w, h);}

画圆角矩形- drawRoundRect() & drawRoundedRect()

绘制圆角矩形有 2 个方法:drawRoundRect() 和 drawRoundedRect(),需要给定圆角矩形左上角的坐标、长、宽、圆角的半径。

当 drawRoundedRect() 中第 7 个参数 Qt::SizeMode 为 Qt::RelativeSize 时,表示圆角半径的单位是百分比,取值范围是 [0, 100],此时 drawRoundedRect() 等价于 drawRoundRect(),其实底层是用这个百分比和对应边长的一半相乘得到圆角的半径(单位是像素)。Qt::SizeMode 为 Qt::AbsoluteSize 时,表示圆角半径的单位是像素。

void RoundRectWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.setRenderHint(QPainter::Antialiasing);    painter.setBrush(Qt::lightGray);    painter.translate(30, 30);    painter.drawRoundRect(0, 0, 100, 100, 50, 50); // 50%, 50%    painter.drawRoundedRect(130, 0, 100, 100, 50, 50, Qt::AbsoluteSize); // 50px, 50px    painter.drawRoundedRect(260, 0, 100, 100, 100, 100, Qt::RelativeSize); // 100%, 100%}

画圆、椭圆 - drawEllipse()

void EllipseWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.setRenderHint(QPainter::Antialiasing);    painter.translate(30, 30);    painter.drawRect(0, 0, 200, 100);    // 椭圆的包围矩形    painter.setBrush(Qt::lightGray);    painter.drawEllipse(0, 0, 200, 100); // 椭圆    painter.drawEllipse(230, 0, 100, 100); // 圆}

画弧、弦、饼图 - drawArc()、drawChord()、drawPie()

画弧使用 drawArc()
画弦使用 drawChord()
画饼图用 drawPie()

void QPainter::drawArc(const QRectF & rectangle, int startAngle, int spanAngle)void QPainter::drawPie(const QRectF & rectangle, int startAngle, int spanAngle)void QPainter::drawChord(const QRectF & rectangle, int startAngle, int spanAngle)

这里写图片描述
rectangle: 包围矩形
startAngle: 开始的角度,单位是十六分之一度,如果要从 45 度开始画,则 startAngle 为 45 * 16
spanAngle: 覆盖的角度,单位是十六分之一度
绘制圆心为包围矩形的正中心,0 度在圆心的 X 轴正方向上
角度的正方向为逆时针方向
这里写图片描述

void ArcChordPieWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    painter.setRenderHint(QPainter::Antialiasing);    static int startAngle = 45 * 16; // 开始角度是 45 度    static int spanAngle = 130 * 16; // 覆盖角度为 130 度    static QRectF boundingRect(0, 0, 150, 150); // 包围矩形    painter.translate(30, 30);    painter.setBrush(Qt::NoBrush);    painter.drawRect(boundingRect); // 绘制包围矩形    painter.setBrush(Qt::lightGray);    painter.drawArc(boundingRect, startAngle, spanAngle); // 画弧    painter.translate(180, 0);    painter.setBrush(Qt::NoBrush);    painter.drawRect(boundingRect); // 绘制包围矩形    painter.setBrush(Qt::lightGray);    painter.drawChord(boundingRect, startAngle, spanAngle); // 画弦    painter.translate(180, 0);    painter.setBrush(Qt::NoBrush);    painter.drawRect(boundingRect); // 绘制包围矩形    painter.setBrush(Qt::lightGray);    painter.drawPie(boundingRect, startAngle, spanAngle); // 画饼图}

绘制 QPixmap - drawPixmap()

void MainWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    QPixmap pixmap(":/img/Butterfly.png"); // 从资源文件读取 pixmap    painter.drawPixmap(0, 0, pixmap); // 绘制 pixmap}

绘制 QImage - drawImage()

void MainWidget::paintEvent(QPaintEvent *) {    QPainter painter(this);    QImage image(":/img/Butterfly.png"); // 从资源文件读取 image    painter.drawImage(0, 0, image); // 绘制 image}

绘制路径QPainterPath - drawPath()

    QPainterPath path;      path.addEllipse(-4, -4, 8, 8);//添加一个圆      path.addRect(-5, -5, 10, 10); //添加一个矩形      painter.drawPath(path);  

填充与擦除

/使用画刷填充一个矩形区域  painter.fillRect(QRect(10,100,150,20), QBrush(Qt::darkYellow));  //擦除一个矩形区域的内容  painter.eraserRect(QRect(50,0,50,120)); 
原创粉丝点击