QPainter绘图基本使用

简述

QT中与绘图相关的类主要有QPainter和QPaintDevice
QPainter:绘制器,用来执行绘图的操作,如绘制线、圆、矩形… 可以类比成在黑板上使用的工具集合,比如尺子、圆规、粉笔…
QPaintDevice:绘图设备,是一个抽象出来的绘图设备,实例化有QWidget、Qimage… 可以类比于一块黑板,可以在画圆,直线、矩形、写字…

使用

1、继承QWidget,重写paintEvent方法。
2、在paintEvent函数中创建一个QPainter对象,并将该类指定为父对象。
3、设置我们需要的参数,比如Pen(笔)、Brush(画刷)…
4、调用对应的方法去绘制图形,如drawLine(画直线)、drawEllipse(画椭圆)…
接下来绘制一根直线来看看效果,demo如下

#include <QApplication>
#include <QPainter>
#include <QPen>
#include <QWidget>

class myPaint : public QWidget
{
protected:
    void paintEvent(QPaintEvent * event) override
    {
        QPainter painter(this);
        QPen pen;
        pen.setColor(QColor(Qt::blue));//设置笔颜色
        pen.setWidth(4);//设置笔宽度
        painter.setPen(pen);//设置为要绘制的笔
        painter.drawLine(QPoint(0, 0), QPoint(100, 100));//画线
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    myPaint window;
    window.resize(200, 200);
    window.show();

    return a.exec();
}

效果图如下
在这里插入图片描述
我们绘制的是一个起点(0, 0), 终点(100, 100)的蓝色直线如图所示,由此我们也可以知道QT中的默认坐标系是红色箭头标示。

qt中调用update(),或者拉动窗口大小都会触发这个重绘事件。

常用方法介绍

  • drawLine(绘制线段)
函数描述
drawLine(const QLineF &)根据QLineF对象值绘制一条直线
drawLine(const QLine &)根据QLine对象值绘制一条直线
drawLine(int , int , int , int )显示给定两个点坐标绘制一条直线
drawLine(const QPoint &, const QPoint &)给定两个QPoint点信息绘制一条直线
drawLine(const QPointF &, const QPointF &)给定两个QPointF点信息绘制一条直线
drawLines(const QPointF *, int )给定多个点并指定直线条数绘制多条直线
drawLines(const QVector &)根据QLineF直线集合绘制多条直线
drawLines(const QVector &)根据QLine直线集合绘制多条直线

点信息QPoint和QPointF,直线信息QLine和QLineF,其中带F的是精度更高的浮点型版本,没带F的只支持整形。QLine和QLineF中支持设置线段角度以及获取角度等信息,具体的使用可以查看帮助文档。

  • drawRect(绘制矩形)
  • drawRects(绘制多矩形)
  • drawEllipse(绘制椭圆)
  • drawArc(绘制弧)
  • drawChord(绘制弦)
  • drawPie(绘制扇形)
  • drawRoundedRect(绘制带倒角矩形)
  • drawPoint(绘制点)
  • drawPoints(绘制多个点)
  • drawConvexPloygon(绘制凸多边形)
  • drawPolyline(绘制多段线)
  • drawPolygon(绘制多边形)
  • drawText(绘制文本)

如需使用以上这些图形,绘制接口具体参数参考助手使用,使用大致一致,这里就不一一列举了。

  • drawPath(使用当前笔绘制轮廓,使用当前笔刷绘制填充,绘制给定的画家路径。)
    void QPainter::drawPath(const QPainterPath &path);

QPainterPath类为绘制操作提供了一个容器,允许构造和重用图形形状。画家路径是由许多图形构建块(如矩形、椭圆、直线和曲线)组成的对象。构建块可以在封闭的子路径中连接,例如作为一个矩形或椭圆。闭合路径有相同的起点和终点。或者它们可以独立地作为未封闭的子路径存在,比如直线和曲线。与正常的绘图操作相比,画家路径的主要优势在于,复杂的形状只需要创建一次;然后可以只调用QPainter::drawPath()函数多次绘制。

这里我们写个例子看看具体的使用

#include <QApplication>
#include <QPainter>
#include <QPen>
#include <QWidget>

class myPaint : public QWidget
{
protected:
    void paintEvent(QPaintEvent * event) override
    {
        QPainter painter(this);
        QPainterPath ph;
        QBrush bs(QColor(255, 255, 0));//画刷颜色
        painter.setBrush(bs);//设置画刷
        ph.moveTo(20, 20);//移动当前点
        ph.lineTo(120, 20);//创建从当前点到(120, 20)的线段
        //ph.moveTo(120, 20);//移动当前点
        ph.lineTo(100, 100);//创建从当前点到(100, 100)的线段
        ph.closeSubpath();//关闭绘制路线
        painter.drawPath(ph);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    myPaint window;
    window.resize(200, 200);
    window.show();

    return a.exec();
}

运行看看效果
在这里插入图片描述

这样我们构成的是一个封闭的区域,所以画刷能够将其区域显示出来,我们将ph.moveTo(120, 20);取消注释,再看看效果
在这里插入图片描述
这里实际上是两个线段,并不构成一个区域,所以前后并未进行连接,画刷也没有进行绘制。

例程

这里仿QT自带例程analogclock写了一个时钟,加深一下对QPainter的使用。
先看一下效果
在这里插入图片描述
这里为了简略没有标明数值,也没有使用像例程中添加不规则形状,都是采用画线的方式来实现的。
实现代码如下:

#include <QApplication>
#include <QPainter>
#include <QPen>
#include <QRect>
#include <QColor>
#include <QTimer>
#include <QTime>
#include <QDebug>

class myClock : public QWidget
{
public:
    myClock(QWidget *parent = nullptr):QWidget(parent)
    {
        timer = new QTimer;
        timer->setInterval(1000);
        connect(timer, &QTimer::timeout, this, [=](){update();});
        timer->start();
    }

public:
    void paintEvent(QPaintEvent * event) override
    {
        QTime currentTime = QTime::currentTime();
        QPainter painter(this);
        QPen pen;
        pen.setWidth(3);
        pen.setColor(QColor(Qt::blue));
        painter.setPen(pen);
        //设置渲染,抗齿距
        painter.setRenderHint(QPainter::Antialiasing);
        //移动坐标轴,让原点处于窗口中心位置
        painter.translate(size().width()/2, size().height()/2);
        painter.drawPoint(0, 0);
        //绘制小刻度
        for(int ii = 0; ii < 60; ii++)
        {
            painter.rotate(6);//顺时针旋转6°
            painter.drawLine(size().width()/3, 0, size().width()/3 + 10, 0);
        }
        //绘制大刻度
        pen.setColor(QColor(Qt::black));
        painter.setPen(pen);
        for(int ii = 0; ii < 12; ii++)
        {
            painter.rotate(30);//顺时针旋转30°
            painter.drawLine(size().width()/3 - 5, 0, size().width()/3 + 10, 0);
        }
        //绘制时针
        painter.save();
        pen.setColor(QColor(Qt::black));
        pen.setWidth(10);
        painter.setPen(pen);
        //计算时针需要转动的角度
        painter.rotate(((currentTime.hour()%12) * 30 + ((double)currentTime.minute()/60 * 30) + (((double)currentTime.second()/(60*12)) * 6) - 90));
        painter.drawLine(-size().width()/30, 0, size().width()/6, 0);
        painter.restore();
        //绘制分针
        painter.save();
        pen.setColor(QColor(Qt::blue));
        pen.setWidth(8);
        painter.setPen(pen);
        //计算分针需要转动的角度
        painter.rotate((currentTime.minute() * 6 + ((double)currentTime.second()/60 * 6) - 90));
        painter.drawLine(-size().width()/20, 0, size().width()/3-30, 0);
        painter.restore();
        //绘制秒针
        painter.save();
        pen.setColor(QColor(Qt::green));
        pen.setWidth(6);
        painter.setPen(pen);
        //计算秒针需要转动的角度
        painter.rotate(currentTime.second() * 6 - 90);
        painter.drawLine(-size().width()/15, 0, size().width()/3-20, 0);
        painter.restore();
    }
private:
    QTimer *timer;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    myClock window;
    window.resize(600, 600);
    window.show();

    return a.exec();
}

定时器每隔一秒钟调用update()进行根据获取的系统时间进行界面重绘,主要需要理解QPainter坐标系以及绘制图形位置的计算。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

复杂的世界311

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值