二十四、双缓冲机制

二十四、双缓冲机制

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

实现以下实例

接下来我们将一一介绍实现的功能

首先我们创建一个QMainWindow工程

继续创建一个c++Class文件,继承QWidget,取名为“drawPro”,后面我们的主要功能在这个类进行实现。

首先看drawpro.h

#ifndef DRAWPRO_H
#define DRAWPRO_H#include <QWidget>#include<QtGui>
#include<QMouseEvent>
#include<QPaintEvent>
#include<QResizeEvent>
#include<QColor>
#include<QPen>
#include<QPixmap>
#include<QPainter>
#include<QPalette>class drawPro : public QWidget
{Q_OBJECT
public:explicit drawPro(QWidget *parent = nullptr);void mousePressEvent(QMouseEvent *); //鼠标点击事件void mouseMoveEvent(QMouseEvent *); //鼠标移动事件void paintEvent(QPaintEvent *); //绘图事件void resizeEvent(QResizeEvent *);signals:private:QPixmap *pix;QPoint startPos;QPoint endPos;int style,widths;QColor color;public slots:void setStyle(int); //设置风格void setWidth(int); //设置线宽度void setColor(QColor); //设置线颜色void clearFunc();     //清除函数};#endif // DRAWPRO_H

 我们需要重写鼠标点击事件、鼠标移动事件、绘制事件、大小调整事件。并且也要实现设置风格、线的宽度、线的颜色和清除函数。

drawpro.cpp

实现构造函数

drawPro::drawPro(QWidget *parent) : QWidget(parent)
{setAutoFillBackground(true);setPalette(QPalette(Qt::white));pix=new QPixmap(size());pix->fill(Qt::white);setMinimumSize(600,400);
}

首先把自动填充背景打开,设置背景颜色为白色,然后创建QPixmap对象,并设置大小为窗口的大小,填充颜色为白色。

QPixmap::QPixmap(const QSize &size):

这是一个重载函数。
构造给定大小的像素图。
警告:这将创建一个带有未初始化数据的QPixmap。在使用QPainter绘图之前,调用fill()来用适当的颜色填充像素图。

void QPixmap::fill(const QPaintDevice *device, const QPoint &p):

这个功能已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。
使用QPainter或填充(QColor)过载代替。

void setMinimumSize(int minw, int minh):

此属性保存小部件的最小大小
不能将小部件调整为小于最小小部件大小的大小。如果当前大小较小,则小部件的大小将强制为最小大小。
这个函数设置的最小大小将覆盖QLayout定义的最小大小。为了取消最小大小的设置,使用QSize(0,0)的值。
默认情况下,此属性包含宽度和高度为零的大小。

实现set系列函数

void drawPro::setStyle(int s)
{style=s;
}void drawPro::setWidth(int w)
{widths=w;
}void drawPro::setColor(QColor c)
{color=c;
}

实现清除函数

void drawPro::clearFunc() //创建一个新的pixmap把原来的pixmap覆盖掉,就形成了清除功能
{QPixmap *clearPixmap=new QPixmap(size());clearPixmap->fill(Qt::white);pix=clearPixmap;update();
}

创建一个新的QPixmap对象覆盖旧的QPixmap对象。进而实现了清除功能。但是要记得更新

实现鼠标移动事件

void drawPro::mouseMoveEvent(QMouseEvent *m) //鼠标移动事件
{QPainter *painter=new QPainter;QPen pen;pen.setStyle((Qt::PenStyle)style);pen.setWidth(widths);pen.setColor(color);painter->begin(pix);painter->setPen(pen);painter->drawLine(startPos,m->pos());painter->end();startPos=m->pos();update();
}

初始化笔的一些值,然后把笔放在绘制对象里,让笔跟着绘制对象的绘制直线函数进行绘图。

bool QPainter::begin(QPaintDevice *device) :

开始绘制绘制设备,如果成功返回true;否则返回false。
注意,当调用begin()时,所有的绘制设置(setPen(), setBrush()等)都会重置为默认值。

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

这是一个重载函数。
从p1到p2画一条线。

QPoint QMouseEvent::pos() const:

返回鼠标光标相对于接收事件的小部件的位置。
如果由于鼠标事件而移动小部件,请使用globalPos()返回的全局位置来避免抖动运动。

bool QPainter::end():

绘画结束。绘制时使用的任何资源都会被释放。通常不需要调用this,因为它是由析构函数调用的。
如果画工不再活动则返回true;否则返回false。

实现鼠标点击事件

void drawPro::mousePressEvent(QMouseEvent *m)
{startPos=m->pos();
}

实现绘制事件

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

用于在窗口中绘制一个图片。具体来说,它使用了QPainter类来创建一个画家对象,然后使用drawPixmap()函数在窗口中绘制一个图片。其中,QPoint(0,0)表示图片在窗口中的位置,*pix表示要绘制的图片对象。需要注意的是,这段代码没有对图片进行缩放或裁剪,因此图片会按照原始大小显示在窗口中。 

void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap):

这是一个重载函数。
在给定点的原点上绘制给定的像素图

实现大小调整事件

void drawPro::resizeEvent(QResizeEvent *r)
{if(height() > pix->height() || width() > pix->width()){QPixmap *newPix=new QPixmap(size());newPix->fill(Qt::white);QPainter ps(newPix);ps.drawPixmap(QPoint(0,0),*pix);pix=newPix;}QWidget::resizeEvent(r);
}

当窗口大小改变时,会触发resizeEvent()函数。在函数中,首先判断当前窗口的高度和宽度是否大于原始图片的高度和宽度,如果是,则创建一个新的QPixmap对象newPix,并将其填充为白色。接着,创建一个QPainter对象ps,将原始图片pix绘制在newPix上,并将pix指向newPix。最后,调用QWidget的resizeEvent()函数。

这段代码的作用是在窗口大小改变时,根据窗口大小动态调整图片的大小,并将原始图片绘制在新的图片上。如果窗口变大,则新的图片会被填充为白色,并将原始图片绘制在新的图片上;如果窗口变小,则原始图片会被裁剪。

void QWidget::resizeEvent(QResizeEvent *event):

此事件处理程序可以在子类中重新实现,以接收在事件参数中传递的小部件调整大小事件。当resizeEvent()被调用时,小部件已经有了新的几何形状。旧的大小可以通过QResizeEvent::oldSize()来访问。
处理完调整大小事件后,小部件将被擦除并立即接收一个绘制事件。在此处理程序中不需要(或不应该)进行绘图。

完整代码

#include "drawpro.h"drawPro::drawPro(QWidget *parent) : QWidget(parent)
{setAutoFillBackground(true);setPalette(QPalette(Qt::white));pix=new QPixmap(size());pix->fill(Qt::white);setMinimumSize(600,400);
}void drawPro::setStyle(int s)
{style=s;
}void drawPro::setWidth(int w)
{widths=w;
}void drawPro::setColor(QColor c)
{color=c;
}void drawPro::clearFunc() //创建一个新的pixmap把原来的pixmap覆盖掉,就形成了清除功能
{QPixmap *clearPixmap=new QPixmap(size());clearPixmap->fill(Qt::white);pix=clearPixmap;update();
}void drawPro::mouseMoveEvent(QMouseEvent *m) //鼠标移动事件
{QPainter *painter=new QPainter;QPen pen;pen.setStyle((Qt::PenStyle)style);pen.setWidth(widths);pen.setColor(color);painter->begin(pix);painter->setPen(pen);painter->drawLine(startPos,m->pos());painter->end();startPos=m->pos();update();
}void drawPro::mousePressEvent(QMouseEvent *m)
{startPos=m->pos();
}void drawPro::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.drawPixmap(QPoint(0,0),*pix);
}void drawPro::resizeEvent(QResizeEvent *r)
{if(height() > pix->height() || width() > pix->width()){QPixmap *newPix=new QPixmap(size());newPix->fill(Qt::white);QPainter ps(newPix);ps.drawPixmap(QPoint(0,0),*pix);pix=newPix;}QWidget::resizeEvent(r);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>#include"drawpro.h"#include<QLabel>
#include<QToolButton>
#include<QToolBar>
#include<QComboBox>
#include<QSpinBox>
#include<QColorDialog>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void createToolBarFunc();private:Ui::MainWindow *ui;drawPro *draw;QLabel *labelStyle;QComboBox *comboboxLabelStyle;QLabel *labelWidth;QSpinBox *spinboxLabelWidth;QToolButton *colorButton;QToolButton *clearButton;private slots:void dispStyle();void dispColor();
};
#endif // MAINWINDOW_H

mainwindow.cpp

首先实现构造函数

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);draw=new drawPro;setCentralWidget(draw);createToolBarFunc();setMinimumSize(600,400);dispStyle();draw->setWidth(spinboxLabelWidth->value());draw->setColor(Qt::black);
}

void QMainWindow::setCentralWidget(QWidget *widget):

将给定的小部件设置为主窗口的中心小部件。
注意:QMainWindow获取小部件指针的所有权,并在适当的时候删除它。

void MainWindow::createToolBarFunc()
{QToolBar *toolBar=addToolBar("Tool");labelStyle=new QLabel("线型风格:");comboboxLabelStyle=new QComboBox;comboboxLabelStyle->addItem("实线",static_cast<int>(Qt::SolidLine));comboboxLabelStyle->addItem("冲线",static_cast<int>(Qt::DashLine));comboboxLabelStyle->addItem("点点线",static_cast<int>(Qt::DashDotDotLine));comboboxLabelStyle->addItem("虚线",static_cast<int>(Qt::DotLine));connect(comboboxLabelStyle,SIGNAL(activated(int)),this,SLOT(dispStyle()));labelWidth=new QLabel("线型宽度:");spinboxLabelWidth=new QSpinBox();connect(spinboxLabelWidth,SIGNAL(valueChanged(int)),draw,SLOT(setWidth(int)));colorButton=new QToolButton;QPixmap pixmap(20,20);pixmap.fill(Qt::black);colorButton->setIcon(QIcon(pixmap));connect(colorButton,&QToolButton::clicked,this,&MainWindow::dispColor);clearButton=new QToolButton;clearButton->setText("清除");connect(clearButton,&QToolButton::clicked,draw,&drawPro::clearFunc);toolBar->addWidget(labelStyle);toolBar->addWidget(comboboxLabelStyle);toolBar->addWidget(labelWidth);toolBar->addWidget(spinboxLabelWidth);toolBar->addWidget(colorButton);toolBar->addWidget(clearButton);}

QToolBar *QMainWindow::addToolBar(const QString &title):

这是一个重载函数。
创建QToolBar对象,将其窗口标题设置为title,并将其插入到顶部工具栏区域。

实现槽函数

void MainWindow::dispStyle()
{draw->setStyle(comboboxLabelStyle->itemData(comboboxLabelStyle->currentIndex(),Qt::UserRole).toInt());
}void MainWindow::dispColor()
{QColor color=QColorDialog::getColor(static_cast<int>(Qt::black),this);if(color.isValid()){draw->setColor(color);QPixmap ps(20,20);ps.fill(color);}
}

完整代码

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);draw=new drawPro;setCentralWidget(draw);createToolBarFunc();setMinimumSize(600,400);dispStyle();draw->setWidth(spinboxLabelWidth->value());draw->setColor(Qt::black);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::createToolBarFunc()
{QToolBar *toolBar=addToolBar("Tool");labelStyle=new QLabel("线型风格:");comboboxLabelStyle=new QComboBox;comboboxLabelStyle->addItem("实线",static_cast<int>(Qt::SolidLine));comboboxLabelStyle->addItem("冲线",static_cast<int>(Qt::DashLine));comboboxLabelStyle->addItem("点点线",static_cast<int>(Qt::DashDotDotLine));comboboxLabelStyle->addItem("虚线",static_cast<int>(Qt::DotLine));connect(comboboxLabelStyle,SIGNAL(activated(int)),this,SLOT(dispStyle()));labelWidth=new QLabel("线型宽度:");spinboxLabelWidth=new QSpinBox();connect(spinboxLabelWidth,SIGNAL(valueChanged(int)),draw,SLOT(setWidth(int)));colorButton=new QToolButton;QPixmap pixmap(20,20);pixmap.fill(Qt::black);colorButton->setIcon(QIcon(pixmap));connect(colorButton,&QToolButton::clicked,this,&MainWindow::dispColor);clearButton=new QToolButton;clearButton->setText("清除");connect(clearButton,&QToolButton::clicked,draw,&drawPro::clearFunc);toolBar->addWidget(labelStyle);toolBar->addWidget(comboboxLabelStyle);toolBar->addWidget(labelWidth);toolBar->addWidget(spinboxLabelWidth);toolBar->addWidget(colorButton);toolBar->addWidget(clearButton);}void MainWindow::dispStyle()
{draw->setStyle(comboboxLabelStyle->itemData(comboboxLabelStyle->currentIndex(),Qt::UserRole).toInt());
}void MainWindow::dispColor()
{QColor color=QColorDialog::getColor(static_cast<int>(Qt::black),this);if(color.isValid()){draw->setColor(color);QPixmap ps(20,20);ps.fill(color);}
}

本次项目的难度在于实现上面几个事件函数,需要注意一些细节,比如在改变笔的颜色的时候,我们应该先保存当前绘制的图片。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/215544.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

配置BFD多跳检测示例

BFD简介 双向转发检测BFD&#xff08;Bidirectional Forwarding Detection&#xff09;是一种全网统一的检测机制&#xff0c;用于快速检测、监控网络中链路或者IP路由的转发连通状况。 为了减小设备故障对业务的影响&#xff0c;提高网络的可靠性&#xff0c;网络设备需要能够…

vue3中实现el-tree通过ctrl或shift批量选择节点并高亮展示

一、看效果&#xff1a; 按住ctrl键实现单个多选 按住shift实现区间范围多选 二、代码&#xff1a; vue页面 <template><el-treeclass"w100%":data"$.treeData"ref"treeTab…

SQL中的三值逻辑:TRUE、FALSE 和 UNKNOWN。

在SQL中&#xff0c;通常采用三值逻辑处理条件表达式的真值。这种逻辑是基于三种可能的真值状态&#xff1a;TRUE、FALSE 和 UNKNOWN。 TRUE&#xff08;真&#xff09;&#xff1a; 表示条件为真或成立。 FALSE&#xff08;假&#xff09;&#xff1a; 表示条件为假或不成立。…

python实战教学之python版“张万森,好久不见”

前言 WINTER IS COMING 最近《一闪一闪亮星星》的电影在火热预售中&#xff0c;家人们抢到票了嘛&#xff0c;前两天小编写了一篇“张万森&#xff0c;下雪了”的文章后&#xff0c;收到了不少小伙伴的反馈&#xff1a;“代码的运行结果只有文字&#xff0c;没有雪花啊”&#…

C# OpenCvSharp DNN 深度神经网络下的风格迁移模型

目录 介绍 效果 项目 代码 下载 C# OpenCvSharp DNN 深度神经网络下的风格迁移模型 介绍 深度神经网络下的风格迁移模型&#xff0c;适用于OpenCv、EmguCv。 斯坦福大学李飞飞团队的风格迁移模型是一种基于深度学习的图像处理技术&#xff0c;可以将一张图像的风格转移…

全面解析ucrtbased.dll找不到的解决方法,快速解决dll问题

在计算机编程和软件开发中&#xff0c;我们经常会遇到一些陌生的DLL文件&#xff0c;其中就包括了ucrtbased.dll。那么&#xff0c;ucrtbased.dll是什么&#xff1f;它有什么作用&#xff1f;又该如何正确使用呢&#xff1f;本文将详细解析ucrtbased.dll的定义、功能以及应用&a…

Python:核心知识点整理大全8-笔记

目录 ​编辑 4.5 元组 4.5.1 定义元组 dimensions.py 4.5.2 遍历元组中的所有值 4.5.3 修改元组变量 4.6 设置代码格式 4.6.1 格式设置指南 4.6.2 缩进 4.6.3 行长 4.6.4 空行 4.6.5 其他格式设置指南 4.7 小结 第5章 if语句 5.1 一个简单示例 cars.py 5.2 条…

以企业架构为中心的SABOE数字化转型五环法

文章目录 01 传统企业数字化转型面临诸多挑战02 SABOE数字化转型五环法为企业转型破除迷雾 01 传统企业数字化转型面临诸多挑战 即将过去的2023年&#xff0c;chatGPT大模型、数据资产入表等事件的发生&#xff0c;标志着数字经济正在加速发展。数字经济是人类社会继农业经济、…

二进制、八进制、十进制、十六进制之间转换 原码、反码、补码

进制之间转换 二进制转十进制八进制转十进制十六进制转十进制十进制转二进制十进制转八进制十进制转十六进制二进制转八进制二进制转十六进制八进制转二进制十六进制转二进制原码、反码、补码 对于整数&#xff0c;有四种表示方式&#xff1a; 二进制&#xff1a;0,1&#xff…

Vue:用IDEA开发Vue,标签语法爆红问题处理

一、场景描述 我在IDEA中&#xff0c;学习Vue课程。 入门学习时&#xff0c;是在html文件中&#xff0c;script引入vue.js文件方式。 此时&#xff0c;在html文件中用v-标签&#xff0c;爆红。 二、解决办法 打开 菜单栏 File - Settings 选择 Editor - Files Type&#xf…

一文了解什么是Selenium自动化测试?

一、Selenium是什么&#xff1f; 用官网的一句话来讲&#xff1a;Selenium automates browsers. Thats it&#xff01;简单来讲&#xff0c;Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作浏览器一样。支持的浏…

Hanlp自然语言处理如何再Spring Boot中使用

一、HanLP HanLP (Hankcs NLP) 是一个自然语言处理工具包&#xff0c;具有功能强大、性能高效、易于使用的特点。HanLP 主要支持中文文本处理&#xff0c;包括分词、词性标注、命名实体识别、依存句法分析、关键词提取、文本分类、情感分析等多种功能。 HanLP 可以在 Java、Py…

2023 年山东省职业院校技能大赛(高等职业教育) “信息安全管理与评估”样题

2023 年山东省职业院校技能大赛&#xff08;高等职业教育&#xff09; “信息安全管理与评估”样题 目录 任务 1 网络平台搭建&#xff08;50 分&#xff09; 任务 2 网络安全设备配置与防护&#xff08;250 分&#xff09; 模块二 网络安全事件响应、数字取证调查、应用程序安…

OneNote for Windows10 彻底删除笔记本

找了超多方法&#xff0c;都没有用&#xff0c;我的OneNote都没有文件选项&#xff0c;要在OneDrive中删除&#xff0c;但是一直登不进&#xff0c;然后又找到一个方法&#xff1a; 在网页中打开Office的控制面板 "Sign in to your Microsoft account" 在“最近”一…

DNF 单机联网 搭建教程(附视频)

更多游戏搭建&pvf修改教程请见: DNF教程 注意&#xff1a;请不要将游戏进行商业化&#xff0c;一切后果概不负责。仅供单机&#xff0c;好友之间进行娱乐&#xff01;&#xff01; 注意&#xff1a;请不要将游戏进行商业化&#xff0c;一切后果概不负责。仅供单机&#…

【EI会议征稿】第三届电气、电力与电网系统国际会议(ICEPGS 2024)

第三届电气、电力与电网系统国际会议&#xff08;ICEPGS 2024&#xff09; 2024 3rd International Conference on Electrical, Power and Grid Systems 第三届电气、电力与电网系统国际会议&#xff08;ICEPGS 2024&#xff09;将于2024年1月26-28日在马来西亚吉隆坡隆重举行…

12 位多通道国产芯片ACM32F403/F433 系列,支持 MPU 存储保护功能,应用于工业控制,智能家居等产品中

ACM32F403/F433 芯片的内核基于 ARMv8-M 架构&#xff0c;支持 Cortex-M33 和 Cortex-M4F 指令集。芯片内核 支持一整套DSP指令用于数字信号处理&#xff0c;支持单精度FPU处理浮点数据&#xff0c;同时还支持Memory Protection Unit &#xff08;MPU&#xff09;用于提升应用的…

PHP基础(1)

PHP是一种服务器端脚本语言&#xff0c;是一种用于开发动态Web应用程序的最流行和广泛使用的语言之一。它的全称为“Hypertext Preprocessor”&#xff0c;是一种开源的、可嵌入HTML的脚本语言&#xff0c;可以嵌入到HTML中&#xff0c;也可以直接作为命令行脚本运行。PHP脚本在…

Error: Failed to resolve vue/compiler-sfc——vite项目启动报错——npm run serve

运行项目时&#xff0c;报错如下&#xff1a; Error: Failed to resolve vue/compiler-sfc 根据报错信息的提示&#xff1a;vue的版本必须大于3.2.25&#xff0c;经过查看package.json文件&#xff0c;可以看到vue的版本为3.2.36&#xff0c;是满足条件的。 因此考虑缓存问题&…

Redis数据已经删除了,为什么内存占用还是很高?

Redis数据已经删除了&#xff0c;为什么内存占用还是很高&#xff1f; Redis做了数据删除操作&#xff0c;为什么使用top命令时&#xff0c;还是显示Redis占了很多内存&#xff1f; 没做相关功课的人觉得这个问题有问题&#xff0c;删了数据还说占着内存&#xff0c;面试官不…