• 【Qt】绘图与绘图设备


    QPainter绘图

    Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类

    • QPainter用来执行绘制的操作
    • QPaintDevice是一个二维空间的抽象,这个二维空间允许QPainter在其上面进行绘制,也就是QPainter工作的空间
    • QPaintEngine提供了画笔(QPainter)在不同的设备上进行绘制的统一的接口。QPaintEngine类应用于QPainter和QPaintDevice之间,通常对开发人员是透明的

    可以把QPainter理解成画笔;把QPaintDevice理解成使用画笔的地方,比如纸张、屏幕等;而对于纸张、屏幕而言,肯定要使用不同的画笔绘制,为了统一使用一种画笔,我们设计了QPaintEngine类,这个类让不同的纸张、屏幕都能使用一种画笔

    层次结构

    img

    **Qt 的绘图系统实际上是,使用QPainter在QPainterDevice上进行绘制,它们之间使用QPaintEngine进行通讯(也就是翻译QPainter的指令)


    绘图设备

    绘图设备是指继承QPainterDevice的子类,Qt一共提供了四个这样的类:QPixmap、QBitmap、QImage和 QPicture

    • QPixmap专门为图像在屏幕上的显示做了优化
    • QBitmap是QPixmap的一个子类,它的色深限定为1,可以使用 QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap,因为QBitmap色深小,因此只占用很少的存储空间,所以适合做光标文件和笔刷。
    • QImage专门为图像的像素级访问做了优化
    • QPicture则可以记录和重现QPainter的各条命令。 QPicture将QPainter的命令序列化到一个IO设备,保存为一个平台独立的文件格式

    QPainter绘图实例

    案例1

    首先需要在Widget文件当中重写绘图事件:

    image-20231005155422449


    void MainWindow::paintEvent(QPaintEvent *)
    {
        //实例化画家对象  this指定的是绘图设备 在当前窗口画画
        QPainter painter(this);
    
        //设置画笔
        QPen pen(QColor(255,0,0)); //RGB  目前是红笔
        //设置画笔宽度
        pen.setWidth(3);    
        //设置画笔风格
        pen.setStyle(Qt::DotLine);
        //让画家 使用这个笔
        painter.setPen(pen);
    
    
        //设置画刷=》对于封闭的图形内部会上色  Qt::cyan  Qt::green 也可以...
        QBrush brush(Qt::cyan); //QBrush brush(QColor(255,0,0)) 也可以
        //设置画刷风格
        brush.setStyle(Qt::Dense7Pattern);
        //让画家使用画刷
        painter.setBrush(brush);
    
    
        //画线 =>两点确定一线
        painter.drawLine(QPoint(0,0) , QPoint(100,100));
    
        //画圆 椭圆  ⚪也是椭圆的一种
        painter.drawEllipse( QPoint(100,100) , 50,50); //参数依次代表:圆心 左半径  上半径
    
        //画矩形
        painter.drawRect(QRect(20,20,50,50));//参数依次代表:左上角的点 宽 高
    
        //画文字 =>本质是在矩形框内部画文字
        painter.drawText(QRect(10,200,150,50) , "好好学习,天天向上");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 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
    image-20231005155857200

    案例2-高级设置

    QPainter painter(this);
    painter.drawEllipse(QPoint(100,50) , 50,50); //画圆
    
    //设置 抗锯齿能力=>画的更好  但是效率较低
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawEllipse(QPoint(200,50) , 50,50);//画圆
    
    
    // 画图1->保存点->画图2->恢复到保存点->画图3  所以最后只有画图1和3的矩形
    painter.drawRect(QRect(20,20,50,50));
    
    //移动画家位置开始画画的位置
    painter.translate(100,0);
    
    //保存画家状态
    painter.save();
    
    painter.drawRect(QRect(20,20,50,50));
    
    painter.translate(100,0);//移动画家位置开始画画的位置
    
    //还原画家保存状态 =>在这里的代码当中,只打印了两个矩形,有一个被覆盖了
    painter.restore();
    
    painter.drawRect(QRect(20,20,50,50));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    image-20231005160220261


    案例3:利用画家画资源图片 点击按钮移动图片

    前置工作:

    1.在ui界面当中新增加一个按钮:移动图片

    2.在mainWidget.h当中新增一个成员:int posX = 0

    3.引入资源文件

    构造函数

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        //点击移动按钮,移动图片
        connect(ui->pushButton,&QPushButton::clicked,[=](){
    
            posX+=20;
            //如果要手动调用绘图事件 用update更新
            update();//更新绘图事件
        });
    
        //开启定时器
        QTimer * timer = new QTimer(this);
        timer->start(10);
    
        connect(timer,&QTimer::timeout,[=](){
            posX++;
            update();//更新绘图事件
        });
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    void MainWindow::paintEvent(QPaintEvent *)
    {
        /利用画家 画资源图片 ///
         QPainter painter(this); //画在当前窗口
         QPixmap pix = QPixmap(":/image/tree.png");
    
         //如果超出屏幕,重新从0位置开始往右移动
         if(posX >= this->width()) //this->width()屏幕的宽度  this->height()屏幕的高度
         {
             posX = 0;
         }
    
         painter.drawPixmap(posX,0,pix); //posX:类的成员
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    QtPaintDevice实例

    同理也需要重写绘图事件

    //绘图事件
    void paintEvent(QPaintEvent *);
    
    • 1
    • 2

    Pixmap绘图设备

    //Pixmap绘图设备 会专门为平台做了显示的优化
    QPixmap pix(300,300);//相当于300*300的宽 高的纸张
    
    //填充背景颜色
    pix.fill(Qt::white);
    
    //声明画家
    QPainter painter(&pix);//往pix当中画画
    
    painter.setPen(QPen(Qt::green));//设置画笔颜色
    painter.drawEllipse(QPoint(150,150) , 100,100);//画圆
    
    //保存到磁盘的某个位置
    pix.save("E:\\pix.png");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    QImage 绘图设备

    实例1

    QImage img(300,300,QImage::Format_RGB32); //宽 高
    img.fill(Qt::white);
    
    QPainter painter(&img);
    painter.setPen(QPen(Qt::blue));
    painter.drawEllipse(QPoint(150,150) , 100,100);
    
    //保存
    img.save("E:\\img.png");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    可以对像素进行访问

    void MainWindow::paintEvent(QPaintEvent *)
    {
            QPainter painter(this);
    
            //利用QImage 对像素进行修改
            QImage img;
            img.load("E:/img.png"); //加载图片
    
            //修改像素点
            for(int i = 50 ;i < 100 ; i++)
            {
                for(int j = 50 ; j < 100;j++)
                {
                    QRgb value = qRgb(255,0,0); //像素点类型
                    img.setPixel(i,j,value);//第i行第j列变为value该像素
                }
            }
    
            painter.drawImage(0,0,img);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    image-20231005202013208


    QPicture 绘图设备

    //QPicture 绘图设备  可以记录和重现 绘图指令
    QPicture pic;
    QPainter painter; //可以后面再指定绘图设备
    painter.begin(&pic);  //=>指定绘图设备=>开始往pic上画
    painter.setPen(QPen(Qt::cyan));
    painter.drawEllipse(QPoint(150,150) , 100,100);
    painter.end(); //结束画画
    
    //保存到磁盘
    pic.save("E:\\pic.zt"); //名称和后缀名任意
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后可以在绘图事件当中进行重现:

    void MainWindow::paintEvent(QPaintEvent *)
    {
        //重现QPicture的绘图指令
        QPainter painter(this);
    
        QPicture pic;
        pic.load("E:\\pic.zt");//加载上述保存的图片的路径
        painter.drawPicture(0,0,pic);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

  • 相关阅读:
    电流表指针状态识别原理是什么---豌豆云
    简洁自增ID实现方案
    Ubuntu Seata开机自启动服务
    Python应用爬虫下载QQ音乐歌曲!
    vue3 + ts 权限管理
    01-Spring中事务的实现之编程式事务和声明式事务,以及事务的属性之传播行为,隔离级别,事务的回滚
    OpenSSL 密码库实现证书签发流程详解
    pyhton如何判断字符串中是否只含有数字——isnumeric/isdigit/isdecimal三大函数的区别及实例
    java设计模式之原型模式
    java-php-python-ssm新冠病毒感染者档案信息管理系统计算机毕业设计
  • 原文地址:https://blog.csdn.net/chuxinchangcun/article/details/134043867