龙空技术网

学习QT之双缓冲机制

QT教程 636

前言:

现时各位老铁们对“c语言双缓冲”都比较注重,朋友们都需要分析一些“c语言双缓冲”的相关资讯。那么小编也在网上搜集了一些对于“c语言双缓冲””的相关内容,希望姐妹们能喜欢,看官们一起来了解一下吧!

所谓双缓冲机制,是指在绘制控件时,首先将要绘制的内容绘制在一个图片中,再将图片一次性绘制到控件上。在早期的Qt版本中,若直接在控件上进行绘制工作,则在控件重绘时会产生闪烁的现象,控件重绘频繁时,闪烁尤为明显。双缓冲机制可以有效地消除这种闪烁现象。自Qt 5版本之后,​QWidget​​控件已经能够自动处理闪烁的问题。因此,在控件上直接绘图时,不用再操心显示的闪烁问题,但双缓冲机制在很多场合仍然有其用武之地。当所需绘制的内容较复杂并需要频繁刷新,或者每次只需要刷新整个控件的一小部分时,仍应尽量采用双缓冲机制。

下面通过一个实例来演示双缓冲机制:

一、运行结果

Qt学习基地:C/C++项目实战/Qt5/C语言/c++/数据库/OpenCV/MFC/QT项目-学习视频教程-腾讯课堂

二、具体代码

​​drawwidget.h​​

#ifndef DRAWWIDGET_H#define DRAWWIDGET_H#include <QWidget>#include <QtGui>#include <QMouseEvent>#include <QPaintEvent>#include <QResizeEvent>#include <QColor>#include <QPixmap>#include <QPoint>#include <QPainter>#include <QPalette>class DrawWidget : public QWidget{Q_OBJECTpublic:explicit DrawWidget(QWidget *parent = 0);void mousePressEvent(QMouseEvent *); //重写鼠标按下事件void mouseMoveEvent(QMouseEvent *); //重写鼠标移动事件void paintEvent(QPaintEvent *); //重写绘图事件void resizeEvent(QResizeEvent *); //重写窗体大小变化事件signals:public slots:void setStyle(int);void setWidth(int);void setColor(QColor);void clear();private:QPixmap *pix;QPoint startPos;QPoint endPos;int style;int weight;QColor color;};#endif // DRAWWIDGET_H

​​drawwidget.cpp​​

#include "drawwidget.h"#include <QtGui>#include <QPen>DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent){setAutoFillBackground(true);setPalette(QPalette(Qt::white));pix = new QPixmap(size()); //获取当前窗体的大小新建一个QPixmap对象pix->fill(Qt::white); //将其填充为白色setMinimumSize(60,400); //设置窗体的最小值}void DrawWidget::setStyle(int s){style = s;}void DrawWidget::setWidth(int w){weight = w;}void DrawWidget::setColor(QColor c){color = c;}void DrawWidget::mousePressEvent(QMouseEvent *event){startPos = event->pos();}void DrawWidget::mouseMoveEvent(QMouseEvent *event) //注(1){QPainter *painter = new QPainter;QPen pen;pen.setStyle((Qt::PenStyle)style);pen.setWidth(weight);pen.setColor(color);painter->begin(pix); //注(2)painter->setPen(pen);painter->drawLine(startPos,event->pos());painter->end();startPos = event->pos();update();}void DrawWidget::paintEvent(QPaintEvent *event){QPainter painter(this);painter.drawPixmap(QPoint(0,0),*pix);}void DrawWidget::resizeEvent(QResizeEvent *evnet) //注(3){if(height() > pix->height() || width() > pix->width()){QPixmap *newPix = new QPixmap(size()); //创建一个新的QPixmap对象newPix->fill(Qt::white); //填充QPixmap对象newPix的颜色为白色背景色QPainter painter(newPix);painter.drawPixmap(QPoint(0,0),*pix); //在newPix中绘制原pix中的内容pix = newPix; //将newPix赋值给pix作为新的绘制图形接收对象}QWidget::resizeEvent(evnet); //完成其余的工作}void DrawWidget::clear() //以当前窗口大小创建一个QPixmap对象,然后更新pix,重绘{QPixmap *clearPix = new QPixmap(size());clearPix->fill(Qt::white);pix = clearPix;update();}

注:以上类是继承至QWidget,将其设为QMainWindow的中心区域作为画板

注(1):重定义鼠标移动事件​​mouseMoveEvent()​​​,鼠标移动事件在默认情况下,在鼠标按键被按下的同时拖拽鼠标时被触发。QWidget的​​mouseTracking​​​属性指示是否追踪鼠标,默认为false(不追踪),即在至少有一个鼠标按键被按下的前提下移动鼠标才触发​​mouseMoveEvent()​​​事件,可以通过​​setMouseTracking(bool enable)​​​方法对该属性值进行设置。如果设置为追踪,则无论鼠标按键是否按下,只要鼠标移动,就会触发​​mouseMoveEvent()​​事件。

注(2):​​painter->begin(pix)、painter->end()​​​:以QPixmap对象为QPaintDevice参数绘制。在构造一个QPainter对象时,就立即开始对绘画设置进行绘制。此构造QPainter对象是短时期的,如应定义在​​QWidget::paintEvent()​​​中,并只能调用一次。此构造函数调用开始与​​begin()​​​函数,并且在QPainter的析构函数中自动调用​​end()​​​函数。由于当一个QPainter对象的初始化失败是构造函数不能提供反馈信息,所以在绘制外部设备时应使用​​begin()​​​和​​end()​​函数,如打印机等外部设备。

下面是使用​​begin()​​​和​​end()​​的一个例子

void MyWidget::paintEvent(QPaintEvent *){QPainter p;p.begin(this);p.drawLine(...);p.end();}

类似于下面的形式:

void MyWidget::paintEvent(QPaintEvent *){QPainter p(this);p.drawLine(...);}

注(3):调整绘制区大小函数​​resizeEvent()​​,当窗体的大小发送改变是,效果看起来虽然像是绘制区大小改变了,但实际能够进行绘制的区域仍然没有改变。因为绘图的大小并没有改变,还是原来绘制区窗体的大小,所以在窗体尺寸改变时应及时调整用于绘制的QPixmap对象的大小。

​​mainwindow.h​​

#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include <QToolButton>#include <QLabel>#include <QComboBox>#include <QSpinBox>#include "drawwidget.h"class MainWindow : public QMainWindow{Q_OBJECTpublic:MainWindow(QWidget *parent = 0);~MainWindow();void createToolBar();public slots:void ShowStyle();void ShowColor();private:DrawWidget *drawWidget;QLabel *styleLabel;QComboBox *styleComboBox;QLabel *widthLabel;QSpinBox *widthSpinBox;QToolButton *colorBtn;QToolButton *clearBtn;};#endif // MAINWINDOW_H

​​mainwindow.cpp​​

#include "mainwindow.h"#include <QToolBar>#include <QColorDialog>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent){drawWidget = new DrawWidget;setCentralWidget(drawWidget);createToolBar();setMinimumSize(600,400);ShowStyle();drawWidget->setWidth(widthSpinBox->value());drawWidget->setColor(Qt::black);}MainWindow::~MainWindow(){}void MainWindow::createToolBar(){QToolBar *toolBar = addToolBar("Tool");styleLabel = new QLabel(tr("线型风格"));styleComboBox = new QComboBox;styleComboBox->addItem(tr("SolodLine"),static_cast<int>(Qt::SolidLine));styleComboBox->addItem(tr("DashLine"),static_cast<int>(Qt::DashLine));styleComboBox->addItem(tr("DotLine"),static_cast<int>(Qt::DotLine));styleComboBox->addItem(tr("DashDotLine"),static_cast<int>(Qt::DashDotLine));styleComboBox->addItem(tr("DashDotDotLine"),static_cast<int>(Qt::DashDotDotLine));connect(styleComboBox,SIGNAL(activated(int)),this,SLOT(ShowStyle()));widthLabel = new QLabel(tr("线宽"));widthSpinBox = new QSpinBox;connect(widthSpinBox,SIGNAL(valueChanged(int)),drawWidget,SLOT(setWidth(int)));colorBtn = new QToolButton;QPixmap pixmap(20,20);pixmap.fill(Qt::black);colorBtn->setIcon(QIcon(pixmap));connect(colorBtn,SIGNAL(clicked(bool)),this,SLOT(ShowColor()));clearBtn = new QToolButton();clearBtn->setText(tr("清除"));connect(clearBtn,SIGNAL(clicked(bool)),drawWidget,SLOT(clear()));toolBar->addWidget(styleLabel);toolBar->addWidget(styleComboBox);toolBar->addWidget(widthLabel);toolBar->addWidget(widthSpinBox);toolBar->addWidget(colorBtn);toolBar->addWidget(clearBtn);}void MainWindow::ShowStyle(){drawWidget->setStyle(styleComboBox->itemData(styleComboBox->currentIndex(),Qt::UserRole).toInt());}void MainWindow::ShowColor(){QColor color = QColorDialog::getColor(static_cast<int>(Qt::black),this);if(color.isValid()){drawWidget->setColor(color);QPixmap p(20,20);p.fill(color);colorBtn->setIcon(QIcon(p));}}

【领QT开发教程学习资料,点击下方链接莬费领取↓↓,先码住不迷路~】

点击这里:Qt资料领取(视频教程+文档+代码+项目实战)

标签: #c语言双缓冲