前言:在学习过程中学到了此技术,但是之前解绘图事件与Qpixmap类比较少,所以学起来很吃力,但是学习就是要找对方法才能够进行下去,相信很多同学跟我一样看的云里雾里,即使给了源码,你还是看不懂,需要花大量的时间去了解相关知识,所以此文章更偏向讲解。
双缓冲是什么
双缓冲机制,是指在控件绘制时,会首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上(用来解决绘制闪烁问题),在QT5版本后widget自身已经解决此问题。
但是双缓冲机制很多场合仍有用武之地。比如,当需绘制的内容比较复杂并且需要频繁刷新,或者每次只需要绘制整个控件的一小部分时,依然采用双缓冲机制是需要的。
以下通过介绍实现一个简单的绘图工具,来介绍双缓冲机制的实现。图像先绘制在pixmap上,再将整个pixmap绘制到中央部件的绘图区。
图片来自(5条消息) QT基础之双缓冲机制介绍_墨1024的博客-优快云博客_qt双缓冲
一、
首先确定架构,此项目是由一个继承widget的派生类形成的一个视图显示在主窗口上,所以我们需要在主窗口添加控制线宽、画笔风格清空之类的控件所以用信号槽来进行交互。
二创建、
创建一个继承widget的类,取名DrawWidget,根据需求我靠可以知道,需要将图像画在QPixmap上再将pix对象显示在自身的窗口上,所以需要一个私有的QPixmap指针对象
QPixmap* pix;
有了pix对象如何将他显示在窗口上呢?
1.初始化
我们需要在构造函数里开辟堆内存,然后重写paintEven()事件,关于此事件可以看paintEvent事件触发时机_m0_63647324的博客-优快云博客
//在构造函数里操作
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();
}
剩下的内容会在下一章写出