转载: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()的区别相关推荐

  1. qt repaint 用法_关于Qt 中update()和repaint()的区别

    void QWidget::repaint ( int x, int y, int w, int h, bool erase = TRUE ) [槽] 通过立即调用paintEvent()来直接重新绘 ...

  2. qt repaint 用法_Qt 中update()和repaint()的区别

    void QWidget::repaint ( int x, int y, int w, int h, bool erase = TRUE ) [槽] 通过立即调用paintEvent()来直接重新绘 ...

  3. Qt 中static_cast 和 reinterpret_cast的区别

    Qt 中static_cast 和 reinterpret_cast的区别 1. C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作.因此,常做为隐式类型转换使用.比如: i ...

  4. qt repaint 用法_Qt常用函数 记录(update erase repaint 的区别)

    一界面重载函数 使用方法: 1在头文件里定义函数 protected: void paintEvent(QPaintEvent *event); 2 在CPP内直接重载 void ---------- ...

  5. QT 中QTimer 和 startTimer()的区别

    最需要注意一点 请注意,QTimer的准确性取决于底层操作系统和硬件.timerType参数允许您自定义计时器的准确性.有关不同计时器类型的信息,请参见Qt::TimerType.大多数平台支持20毫 ...

  6. mysql中alter与update,MySQL中update和alter使用区别

    最近在参与IDO老徐的MySQL21天打卡系列,今天在回顾的时候看到一个作业题目是更新表里某个字段值,突然不知道该用update还是alter了,脑子里一下分不清两者的区别了,于是找资料学习了下,现在 ...

  7. qt中update()的粗略理解

    理解 项目中需要通过设置来更新界面,这个过程中若是窗口没有发生变化,即使通过调用update()函数来触发重绘函数重绘窗口,也不能立即显示被重绘的窗口.只有窗口变化的时候才会被显示出来. 示例说明 双 ...

  8. Linux中update和upgrade的区别

    update:更新源里的软件列表.一般指量的变化,侧重更新的意思,主要是为原有的东西增加新功能,或者对已有的部分做出更改等.更新数据源. upgrade:升级你系统里的软件.一般指质的变化,侧重升级的 ...

  9. Qt中Format_ARGB32和Format_ARGB32_Premultiplied的区别

    Format_ARGB32表示非预乘alpha模式 Format_ARGB32_Premultiplied表示预乘alpha模式 预乘alpha: 预乘alpha意思是存储数据中的RGB数据已经是与A ...

最新文章

  1. mysql 切换数据库方案
  2. DBShop前台RCE
  3. elasticsearch配置文件解析
  4. leetcode1047. 删除字符串中的所有相邻重复项
  5. redis源码剖析(十五)——客户端思维导图整理
  6. c#如何嵌套第三方程序_C#程序演示嵌套条件运算符的示例
  7. android gridlayout动态添加_Android-TabLayout-动态设置TabItem的背景Shape.有坑.......
  8. apache php 重写url无效,apache用rewrite重写url时出现问题
  9. 软件测试工程师-Linux介绍、命令
  10. 【英语学习】【WOTD】ephemeral 释义/词源/示例
  11. 微服务架构实战篇(六):Spring boot2.x 集成阿里大鱼短信接口详解与Demo
  12. readelf命令使用
  13. 台式计算机安装无线网卡驱动程序,台式电脑无线网卡驱动程序怎么安装
  14. 手工卸载各版本金蝶K/3客户端的方法
  15. java 适配器模式详解_JAVA设计模式详解(五)----------适配器模式
  16. mysql数据库用户密码_修改mysql数据库的用户名和密码
  17. 苹果xr截屏怎么截_原来苹果手机可实现长截屏!学到了,以后不用羡慕别人手机了...
  18. XiaoHu日志 4/17
  19. 关于理性形象的塑造——歇洛克·福尔摩斯眼中的世界
  20. JAVA开发工程师是什么意思?

热门文章

  1. 学号 20175212童皓桢 《Java程序设计》第8周学习总结
  2. c语言哑铃,使用一副哑铃,做好8个动作,就能练遍全身肌肉
  3. 2022-2028年中国医用纺织品行业市场发展潜力及投资风险预测报告
  4. Huawei 华为云 机器翻译调用 详解
  5. tc command gives Error: Specified qdisc not found on RHEL 8
  6. #304 – 为没有文本标题的控件定义Access 键(Defining an Access Key That Gives Focus to a Different Control)
  7. java解析word 波浪线,word页面边框双波浪线
  8. 分析在智能语音对话流程
  9. ArcGIS配图/地图符号化的一些技巧与相关资料
  10. Elastic:使用 Elastic Stack 来监督系统日志及指标