QT 绘图原理的双缓冲机制(一)

前言:在学习过程中学到了此技术,但是之前解绘图事件与Qpixmap类比较少,所以学起来很吃力,但是学习就是要找对方法才能够进行下去,相信很多同学跟我一样看的云里雾里,即使给了源码,你还是看不懂,需要花大量的时间去了解相关知识,所以此文章更偏向讲解。

双缓冲是什么

双缓冲机制,是指在控件绘制时,会首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上(用来解决绘制闪烁问题),在QT5版本后widget自身已经解决此问题。

但是双缓冲机制很多场合仍有用武之地。比如,当需绘制的内容比较复杂并且需要频繁刷新,或者每次只需要绘制整个控件的一小部分时,依然采用双缓冲机制是需要的。

以下通过介绍实现一个简单的绘图工具,来介绍双缓冲机制的实现。图像先绘制在pixmap上,再将整个pixmap绘制到中央部件的绘图区。


请添加图片描述

 图片来自(5条消息) QT基础之双缓冲机制介绍_墨1024的博客-CSDN博客_qt双缓冲

一、

首先确定架构,此项目是由一个继承widget的派生类形成的一个视图显示在主窗口上,所以我们需要在主窗口添加控制线宽、画笔风格清空之类的控件所以用信号槽来进行交互。

二创建、

创建一个继承widget的类,取名DrawWidget,根据需求我靠可以知道,需要将图像画在QPixmap上再将pix对象显示在自身的窗口上,所以需要一个私有的QPixmap指针对象

 QPixmap* pix;

有了pix对象如何将他显示在窗口上呢?

1.初始化

 我们需要在构造函数里开辟堆内存,然后重写paintEven()事件,关于此事件可以看paintEvent事件触发时机_m0_63647324的博客-CSDN博客​​​​​​

 //在构造函数里操作
 pix = new QPixmap(size());//给定像素图窗口的宽高
 pix->fill(Qt::red);//设置填充颜色
void MainWindow::paintEvent(QPaintEvent *)
{
   // pix->load("C:/Users/Hello/Desktop/阿尼亚.jpg");
    QPainter painter(this);
    painter.drawPixmap(0,0,*pix);
}

创建一个画家类绑定在此窗口上,将pix画在窗口上

三、画图

此时我们就可以在画布pix上画图了,我们看项目演示可以知道,需要在鼠标按下移动时在图像上画图,此时我们就需要重写鼠标的两个事件

void DrawWidget::mousePressEvent(QMouseEvent *e)//鼠标按下
{
      startPos = e->pos();//e就是当前鼠标对象,pos是当前鼠标位置                          
}

因为按下事件函数较短,这里直接实现,我们在头文件里加上一个starPos初始鼠标对象即可(QPoint)型;

void DrawWidget::mouseMoveEvent(QMouseEvent *e)
{
        //QPainter *painter = new QPainter(this);
         QPainter painter;
  
        painter.begin(pix);
        painter.drawLine(startPos, e->pos());
        painter.end();
        startPos = e->pos();

        update();

}

当鼠标移动时,我们创建一个画家对象(创建在堆也可以),但是画家要在哪画呢?我们需要指定一块画布,函数里的begin()函数就是指定在哪里画图,end()结束绘画。绘画时使用的任何资源都将被释放。通常不需要调用它,因为它是由析构函数调用的。

指定好画布之后就可以画画了,这里我们用的是重载的

void QPainter::drawLine(const QPoint &p1, const QPoint &p2)

移动事件触发一次我们就画一点

其实到这里,就已经可以在窗口上画图了

接下来是代码演示

darwwidget.h

#include <QWidget>
#include<QMouseEvent>

class drawWidget : public QWidget
{
    Q_OBJECT
public:
    explicit drawWidget(QWidget *parent = nullptr);
     void paintEvent(QPaintEvent *e);
     void mousePressEvent(QMouseEvent *);
     void mouseMoveEvent(QMouseEvent *);

private:
    QPixmap* pix;
    QPoint startPos;    //记录鼠标的当前位置
signals:

public slots:
};

darwwidget.cpp

#include "drawwidget.h"
#include<QPainter>

drawWidget::drawWidget(QWidget *parent) : QWidget(parent)
{
    setPalette(QPalette(Qt::white));
    pix = new QPixmap(size());//给定像素图窗口的宽高
    pix->fill(Qt::red);
}

void drawWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap(QPoint(0,0), *pix);
}

void drawWidget::mousePressEvent(QMouseEvent *e)
{
     startPos = e->pos();
}

void drawWidget::mouseMoveEvent(QMouseEvent *e)
{
    QPainter painter;

    painter.begin(pix);
    painter.drawLine(startPos, e->pos());
    painter.end();
    startPos = e->pos();

    update();


}

剩下的内容会在下一章写出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值