Qt双缓冲机制与应用方法

1、双缓冲机制

所谓双缓冲机制,是指在绘制控件时,首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上。

在早期的Qt版本中,若直接在控件上进行绘制工作,则在控件重绘时会产生闪烁的现象,控件重绘频繁时,闪烁尤为明显。双缓冲机制可以有效地消除这种闪烁现象。自 Qt 5 版本之后,QWidget 控件已经能够自动处理闪烁的问题。

因此,在控件上直接绘图时,不用再操心显示的闪烁问题,但双缓冲机制在很多场合仍然有其用武之地。当所需绘制的内容较复杂并需要频繁刷新,或者每次只需要刷新整个控件的一小部分时,仍应尽量采用双缓冲机制。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

2、实例效果图

实现一个简单的绘图工具,可以选择线形,线宽,颜色等基本要素。效果图如下所示:

3、实例核心代码

PaintArea.h:

#ifndef PAINTAREA_H
#define PAINTAREA_H
 
#include <QWidget>
#include <QPen>
#include <QBrush>
#include <QMouseEvent>
#include <QPainter>
 
// 绘图区域
class PaintArea : public QWidget
{
    Q_OBJECT
public:
    enum Shape{Dot, Line, Rectangle, RoundRect, Ellipse, Polygon, Polyline, Points, Arc, Path, Text, Pixmap};
    explicit PaintArea(QWidget *parent = nullptr);
    void setShape(Shape shape); // 设置形状
    void setPen(QPen pen); // 设置画笔
    void setBrush(QBrush brush); // 设置画刷
    void clear(); // 清除绘图区域
 
protected:
    void mousePressEvent(QMouseEvent *event); // 鼠标点击事件
    void mouseMoveEvent(QMouseEvent *event); // 鼠标移动事件
    void paintEvent(QPaintEvent *event); // 绘图事件
 
private:
    Shape m_shape; // 形状
    QPen m_pen; // 画笔
    QBrush m_brush; // 画刷
 
    QPixmap *m_pix; // 画布
    QPoint m_posStart; // 鼠标移动绘图的开始坐标
    QPoint m_posEnd; // 鼠标移动绘图的结束坐标
};
 
#endif // PAINTAREA_H

PaintArea.cpp:

#include "PaintArea.h"
 
PaintArea::PaintArea(QWidget *parent) :
    QWidget(parent)
{
    // 设置尺寸
    this->setMinimumSize(600, 300);
 
    // 用调色板设置背景色
    this->setPalette(QPalette(Qt::white));
    this->setAutoFillBackground(true);
 
    // 初始化画布
    m_pix = new QPixmap(size()); // 此QPixmap对象用来准备随时接收绘制的内容
    m_pix->fill(Qt::white); // 填充背景色为白色
}
 
// 鼠标点击事件
void PaintArea::mousePressEvent(QMouseEvent *event)
{
    m_posStart = event->pos();
}
 
// 鼠标移动事件
void PaintArea::mouseMoveEvent(QMouseEvent *event)
{
    QPainter *painter = new QPainter;
 
    // 鼠标移动绘图在画布pix上
    painter->begin(m_pix);
    painter->setPen(m_pen);
 
    if(m_shape == Dot)
        painter->drawLine(m_posStart, event->pos());
    else if(m_shape == Line)
        painter->drawLine(m_posStart, event->pos());
 
    painter->end();
 
    // 形状为Dot时,也就是自由绘图模式时,才时刻更新开始点击坐标
    if(m_shape == Dot)
        m_posStart = event->pos();
 
    this->update();
}
 
// 绘图事件
void PaintArea::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap(QPoint(0,0),*m_pix);
}
 
// 设置形状
void PaintArea::setShape(Shape shape)
{
    m_shape = shape;
}
 
// 设置画笔
void PaintArea::setPen(QPen pen)
{
    m_pen = pen;
}
 
// 设置画刷
void PaintArea::setBrush(QBrush brush)
{
    m_brush = brush;
}
 
// 清除绘图区域
void PaintArea::clear()
{
    QPixmap *clearPix  =new QPixmap(size());
    clearPix->fill(Qt::white);
    m_pix = clearPix;
    this->update();
}

4、双缓冲具体实现代码

下面是实现双缓冲区域的地方:

PaintArea::PaintArea(QWidget *parent) :
    QWidget(parent)
{
    // 设置尺寸
    this->setMinimumSize(600, 300);
 
    // 用调色板设置背景色
    this->setPalette(QPalette(Qt::white));
    this->setAutoFillBackground(true);
 
    // 初始化画布
    m_pix = new QPixmap(size()); // 此QPixmap对象用来准备随时接收绘制的内容
    m_pix->fill(Qt::white); // 填充背景色为白色
}
 
// 鼠标移动事件
void PaintArea::mouseMoveEvent(QMouseEvent *event)
{
    QPainter *painter = new QPainter;
 
    // 鼠标移动绘图在画布pix上
    painter->begin(m_pix);
    painter->setPen(m_pen);
 
    if(m_shape == Dot)
        painter->drawLine(m_posStart, event->pos());
    else if(m_shape == Line)
        painter->drawLine(m_posStart, event->pos());
 
    painter->end();
 
    // 形状为Dot时,也就是自由绘图模式时,才时刻更新开始点击坐标
    if(m_shape == Dot)
        m_posStart = event->pos();
 
    this->update();
}
 
// 绘图事件
void PaintArea::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap(QPoint(0,0), *m_pix);
}

我们不是直接在面板上画画,而且在 Pixmap 里面画画,在这里,我们调用drawPixmap()函数,将用于接收图形绘制的 QPixmap 对象绘制在绘制区窗体控件上,这样就实现了双缓冲机制。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

猜你喜欢

转载自blog.csdn.net/m0_60259116/article/details/130603667