Qt 绘图进阶之二:双缓冲机制与实例
2023-09-27 14:29:13 时间
一、双缓冲机制
所谓双缓冲机制,是指在绘制控件时,首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上。
在早期的Qt版本中,若直接在控件上进行绘制工作,则在控件重绘时会产生闪烁的现象,控件重绘频繁时,闪烁尤为明显。双缓冲机制可以有效地消除这种闪烁现象。自 Qt 5 版本之后,QWidget 控件已经能够自动处理闪烁的问题。
因此,在控件上直接绘图时,不用再操心显示的闪烁问题,但双缓冲机制在很多场合仍然有其用武之地。当所需绘制的内容较复杂并需要频繁刷新,或者每次只需要刷新整个控件的一小部分时,仍应尽量采用双缓冲机制。
二、实例效果图
实现一个简单的绘图工具,可以选择线形,线宽,颜色等基本要素。效果图如下所示:
三、实例核心代码
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();
}
四、双缓冲具体实现代码
下面是实现双缓冲区域的地方:
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 对象绘制在绘制区窗体控件上,这样就实现了双缓冲机制。
五、代码下载
GitHub 下载地址:https://github.com/confidentFeng/QtAppProject
相关文章
- Qt-自定义控件
- QT中多线程QThread使用解疑实例
- qt中在代码中删除界面的槽方法后一定要把定义和声明都删掉否则代码生成器中一直报错
- Qt中创建使用动态链接库详解及实例
- Qt-手动布局
- Qt-qwidget项目入门实例
- QT中信号和信号槽详解
- Qt音视频开发34-不同库版本不同位数的库和头文件的引用
- Qt编写本地摄像头综合应用示例(qcamera/ffmpeg/v4l2等)
- Qt开源作品39-日志输出增强版V2022
- Qt开源作品27-鼠标定位十字线
- Qt开发经验小技巧21-30
- 单例模式:Qt本身就提供了专门的宏 Q_GLOBAL_STATIC 通过这个宏不但定义简单,还可以获得线程安全性
- Qt程序调试之Q_ASSERT断言(它是一个宏,接受布尔值,当其中的布尔值为真时,便什么也不做)
- C++中,如何在标准库的std::string和常用库(Qt,VC等)的QString之间进行选择?
- Qt ------ 我定义的规则 之 对象命名规则
- Qt 多线程(QThreadPool)