Qt中update()和repaint()的区别
转载:https://blog.csdn.net/qq_35396127/article/details/77745204
解释1
voidQWidget::repaint ( int x, int y, int w, int h, bool erase = TRUE ) [槽]
通过立即调用paintEvent()来直接重新绘制窗口部件,如果erase为真,Qt在paintEvent()调用之前擦除区域(x,y,w,h)。
如果w是负数,它被width()-x替换,并且如果h是负数,它被height()-y替换。 如果你需要立即重新绘制,建议使用repaint(),
比如在动画期间。在绝大多数情况下,update()更好,因为它允许Qt来优化速度并且防止闪烁。
警告:如果你在一个函数中调用repaint(),而它自己又被paintEvent()调用,你也许会看到无线循环。
update()函数从来不会产生循环。
void QWidget::update () [槽]
更新窗口部件,当Qt回到主事件中时,它规划了所要处理的绘制事件。这样允许Qt进行优化从而得到比调用repaint()更快的速度和
更少的闪烁。 几次调用update()的结果通常仅仅是一次paintEvent()调用。 Qt通常在paintEvent()调用之前擦除这个窗口部件的区域,仅仅只有在WRepaintNoErase窗口部件标记被设置的时候才不会。
在这区别中关键点是:repaint()是立即调用paintEvent(),而update()是几次执行才调用一次paintEvent()。
这样update()会造成这样的结果:paintEvent()中的任务没有执行完,就又被update().paintEvent()中被积压的任务越来越多。
程序例子:
(1)问题出现时候的情况(10毫秒每次,用update()。paintEvent()积累了很多处理任务):
#include<QPainter>
#include<QDebug>
#include<QMessageBox>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->showMaximized();
i = 0;
realWidth = this->width();
realHeight = this->height();
pixmap =QPixmap(realWidth,realHeight);
connect(this,SIGNAL(haveData(QPoint)),this,SLOT(getPointAndDraw(QPoint)));
connect(&timer,SIGNAL(timeout()),this,SLOT(getPoint()));
timer.start(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::getPoint()
{
if(i < realWidth)
{
point =QPoint(i,(uint(qrand())) % realHeight);
i++;
}
else
{
i = i % realWidth;
point =QPoint(i,(uint(qrand())) % realHeight);
i++;
}
emit haveData(point);
}
void MainWindow::getPointAndDraw(QPoint point)
{
index = point.x();
QPainter painter(&pixmap);
painter.setPen(Qt::green);
painter.drawLine(lastPoint,point);
painter.setPen(Qt::black);
painter.setBrush(Qt::red);
painter.drawRect(index+1,0,5,realHeight);
if(point.x() < realWidth-1)
lastPoint = point;
else
lastPoint =QPoint(0,0);
update();
// this->repaint(index-1,0,5,realHeight);
}
void MainWindow::paintEvent(QPaintEvent *e)
{
//return ;
QPainter painter(this);
QRect target1(0, 0, realWidth,realHeight/5);
QRect target2(0, realHeight/5,realWidth, realHeight/5);
QRect target3(0, 2*realHeight/5,realWidth, realHeight/5);
QRect target4(0, 3*realHeight/5,realWidth, realHeight/5);
QRect target5(0, 4*realHeight/5,realWidth, realHeight/5);
QRect source(0, 0, realWidth,realHeight);
painter.drawPixmap(target1,pixmap,source);
painter.drawPixmap(target2,pixmap,source);
painter.drawPixmap(target3,pixmap,source);
painter.drawPixmap(target4,pixmap,source);
painter.drawPixmap(target5,pixmap,source);
}
void MainWindow::resizeEvent(QResizeEvent *e)
{
realWidth = this->width();
realHeight = this->height();
}
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
(2)每隔1000毫秒刷新一次,用update().一秒种有足够的时间处理paintEvent(),无积累。
#include<QPainter>
#include<QDebug>
#include<QMessageBox>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->showMaximized();
i = 0;
realWidth = this->width();
realHeight = this->height();
pixmap =QPixmap(realWidth,realHeight);
connect(this,SIGNAL(haveData(QPoint)),this,SLOT(getPointAndDraw(QPoint)));
connect(&timer,SIGNAL(timeout()),this,SLOT(getPoint()));
timer.start(1000);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::getPoint()
{
if(i < realWidth)
{
point =QPoint(i,(uint(qrand())) % realHeight);
i++;
}
else
{
i = i % realWidth;
point =QPoint(i,(uint(qrand())) % realHeight);
i++;
}
emit haveData(point);
}
void MainWindow::getPointAndDraw(QPoint point)
{
index = point.x();
QPainter painter(&pixmap);
painter.setPen(Qt::green);
painter.drawLine(lastPoint,point);
painter.setPen(Qt::black);
painter.setBrush(Qt::red);
painter.drawRect(index+1,0,5,realHeight);
if(point.x() < realWidth-1)
lastPoint = point;
else
lastPoint =QPoint(0,0);
update();
//this->repaint(index-1,0,5,realHeight);
}
void MainWindow::paintEvent(QPaintEvent *e)
{
//return ;
QPainter painter(this);
QRect target1(0, 0, realWidth,realHeight/5);
QRect target2(0, realHeight/5, realWidth,realHeight/5);
QRect target3(0, 2*realHeight/5,realWidth, realHeight/5);
QRect target4(0, 3*realHeight/5,realWidth, realHeight/5);
QRect target5(0, 4*realHeight/5,realWidth, realHeight/5);
QRect source(0, 0, realWidth,realHeight);
painter.drawPixmap(target1,pixmap,source);
painter.drawPixmap(target2,pixmap,source);
painter.drawPixmap(target3,pixmap,source);
painter.drawPixmap(target4,pixmap,source);
painter.drawPixmap(target5,pixmap,source);
}
void MainWindow::resizeEvent(QResizeEvent *e)
{
realWidth = this->width();
realHeight = this->height();
}
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
(3)继续改进(10毫秒每次,用repaint()。一次repaint(),一次paintEvent(),无积累).
#include<QPainter>
#include<QDebug>
#include<QMessageBox>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->showMaximized();
i = 0;
realWidth = this->width();
realHeight = this->height();
pixmap =QPixmap(realWidth,realHeight);
connect(this,SIGNAL(haveData(QPoint)),this,SLOT(getPointAndDraw(QPoint)));
connect(&timer,SIGNAL(timeout()),this,SLOT(getPoint()));
timer.start(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::getPoint()
{
if(i < realWidth)
{
point =QPoint(i,(uint(qrand())) % realHeight);
i++;
}
else
{
i = i % realWidth;
point =QPoint(i,(uint(qrand())) % realHeight);
i++;
}
emit haveData(point);
}
void MainWindow::getPointAndDraw(QPoint point)
{
index = point.x();
QPainter painter(&pixmap);
painter.setPen(Qt::green);
painter.drawLine(lastPoint,point);
painter.setPen(Qt::black);
painter.setBrush(Qt::red);
painter.drawRect(index+1,0,5,realHeight);
if(point.x() < realWidth-1)
lastPoint = point;
else
lastPoint =QPoint(0,0);
this->repaint(index-1,0,5,realHeight);
}
void MainWindow::paintEvent(QPaintEvent *e)
{
//return ;
QPainter painter(this);
QRect target1(0, 0, realWidth,realHeight/5);
QRect target2(0, realHeight/5,realWidth, realHeight/5);
QRect target3(0, 2*realHeight/5,realWidth, realHeight/5);
QRect target4(0, 3*realHeight/5,realWidth, realHeight/5);
QRect target5(0, 4*realHeight/5,realWidth, realHeight/5);
QRect source(0, 0, realWidth,realHeight);
painter.drawPixmap(target1,pixmap,source);
painter.drawPixmap(target2,pixmap,source);
painter.drawPixmap(target3,pixmap,source);
painter.drawPixmap(target4,pixmap,source);
painter.drawPixmap(target5,pixmap,source);
}
void MainWindow::resizeEvent(QResizeEvent *e)
{
realWidth = this->width();
realHeight = this->height();
}
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
解释2
Qt里面的重绘和Windows编程里面的重绘差不多。但是Qt的重绘更有特色,更加智能。
在讲之前,先说说paintEvent()
paintEvent()是一个虚函数槽(slot),子类可以对父类的paintEvent进行重写。当调用update(),repaint()的时候,paintEvent()会被调用,另外,当界面有任何改变的时候,paintEvent()也会被调用,这种界面的改变包括界面从隐藏到显示,界面尺寸改变,当然还包括界面内容改变的时候会被调用。paintEvent()是已经被高度优化过的函数,它本身已经自动开启并实现了双缓冲(X11系统需要手动去开启双缓冲),因此Qt中重绘不会引起任何闪烁。
X11系列系统手动开启双缓冲的方法如下:
[cpp] view plaincopyprint?
1. ...
2. extern void qt_x11_set_global_double_buffer(bool);
3. qt_x11_set_global_double_buffer(false);
4. ...
有了paintEvent的知识,现在再来看看update()和repaint()
update和repaint是一类的,需要重绘的对象主动去调用,然后重绘。update和repaint调用之后,都回去调用paintEvent().
repaint(),被调用之后,立即执行重绘,因此repaint是最快的,紧急情况下需要立刻重绘的可以使用repaint()。但是调用repaint的函数不能放到paintEvent中调用。举个例子:有一个继承于QWidget的子类MyWidget,并在子类中对paintEvent进行了重写。我们在MyWidget::myrepaint()中调用repaint()。但是,myrepaint()又被重写的paintEvent()调用。这样调用repaint()的函数又被paintEvent()调用,由于repaint()是立即重绘,而且repaint()在调用paintEvent之前几乎不做任何优化操作,而是会造成死循环,即:先调用repaint(),继而调用paintEvent(),paintEvent()反过来有调用repaint()...如此死循环。
update()跟repaint()比较,update则更加有优越性。update()调用之后并不是立即重绘,而是将重绘事件放入主消息循环中,由main的event loop来统一调度的(其实也是比较快的)。update在调用paintEvent之前,还做了很多优化,如果update被调用了很多次,最后这些update会合并到一个大的重绘事件加入到消息队列,最后只有这个大的update被执行一次。同时也避免了repaint()中所提到的死循环。因此,一般情况下,我们调用update就够了,跟repaint()比起来,update是推荐使用的。
Qt中update()和repaint()的区别相关推荐
- qt repaint 用法_关于Qt 中update()和repaint()的区别
void QWidget::repaint ( int x, int y, int w, int h, bool erase = TRUE ) [槽] 通过立即调用paintEvent()来直接重新绘 ...
- qt repaint 用法_Qt 中update()和repaint()的区别
void QWidget::repaint ( int x, int y, int w, int h, bool erase = TRUE ) [槽] 通过立即调用paintEvent()来直接重新绘 ...
- Qt 中static_cast 和 reinterpret_cast的区别
Qt 中static_cast 和 reinterpret_cast的区别 1. C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作.因此,常做为隐式类型转换使用.比如: i ...
- qt repaint 用法_Qt常用函数 记录(update erase repaint 的区别)
一界面重载函数 使用方法: 1在头文件里定义函数 protected: void paintEvent(QPaintEvent *event); 2 在CPP内直接重载 void ---------- ...
- QT 中QTimer 和 startTimer()的区别
最需要注意一点 请注意,QTimer的准确性取决于底层操作系统和硬件.timerType参数允许您自定义计时器的准确性.有关不同计时器类型的信息,请参见Qt::TimerType.大多数平台支持20毫 ...
- mysql中alter与update,MySQL中update和alter使用区别
最近在参与IDO老徐的MySQL21天打卡系列,今天在回顾的时候看到一个作业题目是更新表里某个字段值,突然不知道该用update还是alter了,脑子里一下分不清两者的区别了,于是找资料学习了下,现在 ...
- qt中update()的粗略理解
理解 项目中需要通过设置来更新界面,这个过程中若是窗口没有发生变化,即使通过调用update()函数来触发重绘函数重绘窗口,也不能立即显示被重绘的窗口.只有窗口变化的时候才会被显示出来. 示例说明 双 ...
- Linux中update和upgrade的区别
update:更新源里的软件列表.一般指量的变化,侧重更新的意思,主要是为原有的东西增加新功能,或者对已有的部分做出更改等.更新数据源. upgrade:升级你系统里的软件.一般指质的变化,侧重升级的 ...
- Qt中Format_ARGB32和Format_ARGB32_Premultiplied的区别
Format_ARGB32表示非预乘alpha模式 Format_ARGB32_Premultiplied表示预乘alpha模式 预乘alpha: 预乘alpha意思是存储数据中的RGB数据已经是与A ...
最新文章
- mysql 切换数据库方案
- DBShop前台RCE
- elasticsearch配置文件解析
- leetcode1047. 删除字符串中的所有相邻重复项
- redis源码剖析(十五)——客户端思维导图整理
- c#如何嵌套第三方程序_C#程序演示嵌套条件运算符的示例
- android gridlayout动态添加_Android-TabLayout-动态设置TabItem的背景Shape.有坑.......
- apache php 重写url无效,apache用rewrite重写url时出现问题
- 软件测试工程师-Linux介绍、命令
- 【英语学习】【WOTD】ephemeral 释义/词源/示例
- 微服务架构实战篇(六):Spring boot2.x 集成阿里大鱼短信接口详解与Demo
- readelf命令使用
- 台式计算机安装无线网卡驱动程序,台式电脑无线网卡驱动程序怎么安装
- 手工卸载各版本金蝶K/3客户端的方法
- java 适配器模式详解_JAVA设计模式详解(五)----------适配器模式
- mysql数据库用户密码_修改mysql数据库的用户名和密码
- 苹果xr截屏怎么截_原来苹果手机可实现长截屏!学到了,以后不用羡慕别人手机了...
- XiaoHu日志 4/17
- 关于理性形象的塑造——歇洛克·福尔摩斯眼中的世界
- JAVA开发工程师是什么意思?
热门文章
- 学号 20175212童皓桢 《Java程序设计》第8周学习总结
- c语言哑铃,使用一副哑铃,做好8个动作,就能练遍全身肌肉
- 2022-2028年中国医用纺织品行业市场发展潜力及投资风险预测报告
- Huawei 华为云 机器翻译调用 详解
- tc command gives Error: Specified qdisc not found on RHEL 8
- #304 – 为没有文本标题的控件定义Access 键(Defining an Access Key That Gives Focus to a Different Control)
- java解析word 波浪线,word页面边框双波浪线
- 分析在智能语音对话流程
- ArcGIS配图/地图符号化的一些技巧与相关资料
- Elastic:使用 Elastic Stack 来监督系统日志及指标