版权声明:若无来源注明,Techie亮博客文章均为原创。 转载请以链接形式标明本文标题和地址:
本文标题:QWidget一生,从创建到销毁事件流     本文地址:http://techieliang.com/2017/11/319/
代码较多,此处显示效果不佳,建议到原文地址查看

最近做UI,有多个窗口嵌套,且所有窗口均用了Layout布局,当运行程序时,主窗口布局有效,而嵌套的窗口布局未生效。

1. 构造函数Resize()

首先我想到的是,我设置了Layout,那么他会自动调整大小,是不是在创建子窗口的时候并没有获取到此窗口在父类布局中占用的位置?那么我在构造的时候分别设置每个子窗口即可。

child_widget->Resize(this->XXXX->size());//XXXX是子窗口一个widget的区域,或者qstackedwidget等某个页面的大小

使用上述类似的指令去重新设置,发现没有任何效果。而根本原因是构造函数中获得的Size()并不对,不是主窗口的真实尺寸。

2. 笨方法-QTimer()

由于时间关系,使用了笨方法。无论如何最后构造完成以后肯定窗口显示了。。。。

那么建立一个定时器,构造的时候启动定时器,连接到槽,然后timeout()以后执行Resize指令,并且stop Timer。。。

此方法确实解决了布局适应的问题,但是建立一个timer,方法并不友好

3. QWidget构造到销毁事件流分析

此处为了方便,不对QWidget做范例分析,直接用QMainWindow做分析,QMainWindow是QWidget的子类。

下面会详细说明分析方法,若需要对QWidget或者其他控件做分析,可以仿照进行。

3.1. 实验项目配置

直接新建一个Qt Widgets项目,为了测试方便,我把默认的菜单栏、工具栏、状态栏都取消了,只添加了一个QPushButton按钮控件。

程序代码如下:

*.pro

  1. QT += core gui
  2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
  3. TARGET = untitled
  4. TEMPLATE = app
  5. DEFINES += QT_DEPRECATED_WARNINGS
  6. SOURCES += \
  7. main.cpp \
  8. mainwindow.cpp
  9. HEADERS += \
  10. mainwindow.h
  11. FORMS += \
  12. mainwindow.ui

mainwindow.ui

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ui version="4.0">
  3. <class>MainWindow</class>
  4. <widget class="QMainWindow" name="MainWindow">
  5. <property name="geometry">
  6. <rect>
  7. <x>0</x>
  8. <y>0</y>
  9. <width>400</width>
  10. <height>300</height>
  11. </rect>
  12. </property>
  13. <property name="windowTitle">
  14. <string>MainWindow</string>
  15. </property>
  16. <widget class="QWidget" name="centralWidget">
  17. <widget class="QPushButton" name="pushButton">
  18. <property name="geometry">
  19. <rect>
  20. <x>190</x>
  21. <y>150</y>
  22. <width>89</width>
  23. <height>24</height>
  24. </rect>
  25. </property>
  26. <property name="text">
  27. <string>PushButton</string>
  28. </property>
  29. </widget>
  30. </widget>
  31. </widget>
  32. <layoutdefault spacing="6" margin="11"/>
  33. <resources/>
  34. <connections/>
  35. </ui>

main.cpp

  1. #include "mainwindow.h"
  2. #include <QApplication>
  3. int main(int argc, char *argv[]) {
  4. QApplication a(argc, argv);
  5. MainWindow w;
  6. w.show();
  7. return a.exec();
  8. }

mainwindow.h

  1. #pragma once
  2. #include <QMainWindow>
  3. namespace Ui {
  4. class MainWindow;
  5. }
  6. class MainWindow : public QMainWindow {
  7. Q_OBJECT
  8. public:
  9. explicit MainWindow(QWidget *parent = 0);
  10. ~MainWindow();
  11. protected:
  12. bool event(QEvent *event) Q_DECL_OVERRIDE;
  13. private:
  14. Ui::MainWindow *ui;
  15. };

mainwindow.cpp

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QEvent>
  4. #include <QDebug>
  5. MainWindow::MainWindow(QWidget *parent) :
  6. QMainWindow(parent),
  7. ui(new Ui::MainWindow) {
  8. qDebug()<<"Befor ui->setupUi(this)";
  9. ui->setupUi(this);
  10. qDebug()<<"After ui->setupUi(this)";
  11. }
  12. MainWindow::~MainWindow() {
  13. delete ui;
  14. }
  15. bool MainWindow::event(QEvent *event) {
  16. qDebug()<<event->type();
  17. QMainWindow::event(event);
  18. }

其实项目很简单,就是直接重写了event(QEvent *event)函数,利用qDebug()输出事件类型。

事件类型通过type调用,返回TYPE枚举类型,此类型在“qcoreevent.h”文件夹存储

  1. enum Type {
  2. None = 0, // invalid event
  3. Timer = 1, // timer event
  4. MouseButtonPress = 2, // mouse button pressed
  5. MouseButtonRelease = 3, // mouse button released
  6. MouseButtonDblClick = 4, // mouse button double click
  7. MouseMove = 5, // mouse move
  8. KeyPress = 6, // key pressed
  9. KeyRelease = 7, // key released
  10. FocusIn = 8, // keyboard focus received
  11. FocusOut = 9, // keyboard focus lost
  12. FocusAboutToChange = 23, // keyboard focus is about to be lost
  13. Enter = 10, // mouse enters widget
  14. Leave = 11, // mouse leaves widget
  15. Paint = 12, // paint widget
  16. Move = 13, // move widget
  17. Resize = 14, // resize widget
  18. Create = 15, // after widget creation
  19. ……………………………………………………………………//太多了,具体自行查看
  20. };

3.2. 结果

直接运行程序就出现了结果,从运行到窗口创建完毕:

同时在main()函数中每个位置增加断点可以看到不同指令的详细执行效果。

  1. Befor ui->setupUi(this)//构造函数开始----MainWindow?w;
  2. QEvent::Type(ChildAdded)
  3. QEvent::Type(WindowTitleChange)
  4. After ui->setupUi(this)//构造函数结束---MainWindow?w结束;
  5. QEvent::Type(PlatformSurface)//---w.show()开始;
  6. QEvent::Type(WinIdChange)
  7. QEvent::Type(WindowIconChange)//icon
  8. QEvent::Type(Polish)//style polish
  9. QEvent::Type(ChildPolished)
  10. QEvent::Type(Move)//调整窗口位置
  11. QEvent::Type(Resize)//调整窗口尺寸
  12. QEvent::Type(Show)//显示
  13. QEvent::Type(CursorChange)
  14. QEvent::Type(ShowToParent)
  15. QEvent::Type(PolishRequest)
  16. QEvent::Type(LayoutRequest)
  17. QEvent::Type(UpdateLater)
  18. QEvent::Type(UpdateRequest)//---w.show()结束
  19. QEvent::Type(WindowActivate)//---a.exec()
  20. QEvent::Type(ActivationChange)
  21. QEvent::Type(Paint)//---a.exec()结束

关闭窗口:

  1. QEvent::Type(NonClientAreaMouseMove)//鼠标移动到关闭
  2. QEvent::Type(NonClientAreaMouseButtonPress)//点击右上角关闭
  3. QEvent::Type(Close)
  4. QEvent::Type(WindowDeactivate)
  5. QEvent::Type(ActivationChange)
  6. QEvent::Type(Hide)
  7. QEvent::Type(HideToParent)
  8. QEvent::Type(UpdateRequest)

3.3. 结果分析

通过构造的事件流可以看到,Qt的设置各个控件的尺寸的操作在构造函数之后,所以在构造函数用Size获取到的尺寸是错误的。

Qt的Event类型有很多,发型不同类型的事件会调用对应的函数,可以看QWidget的API,上述发生事件部分对照关系已经在注释中写出,下面总结一下主要的事件流,出现的先后顺序就是事件发生顺序:

MainWindow?w;

  • 调用构造函数

w.show();

  • QStyle::polish()
  • QWidget::moveEvent()
  • QWidget::resizeEvent()
  • QWidget::showEvent()—–在这里刷新所有嵌入的子页面的size即可实现自适应

a.exec();

  • QWidget::ensurePolished()
  • QWidgetBackingStore::sync()
  • QWidget::paintEvent()

退出:

  • QWidget::closerEvent()

QWidget一生,从创建到销毁事件流的更多相关文章

  1. 监听域对象创建和销毁的Listener

    1.什么是Servlet监听器? 先来看看什么是监听器.监听器是专门用于对其它对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时立即采取相应的行动.Servlet监听器是S ...

  2. JavaScript 事件 事件流 事件对象 事件处理程序 回调函数 error和try...catch和throw

    参考资料: 慕课网 DOM事件探秘    js事件对象 处理 事件驱动: JS是采用事件驱动的机制来响应用户操作的,也就是说当用户对某个html元素进行操作的时候,会产生一个时间,该时间会驱动某些函数 ...

  3. JavaScript Event 事件 事件流 事件对象 事件处理程序 回调函数 error和try...catch和throw

    参考资料: 慕课网 DOM事件探秘    js事件对象 处理 事件驱动: JS是采用事件驱动的机制来响应用户操作的,也就是说当用户对某个html元素进行操作的时候,会产生一个事件,该事件会驱动某些函数 ...

  4. JavaScript事件流原理解析

    一.为什么会有这一篇的文章 国庆前几天由于任务比较重,要赶在国庆前把一个进度的任务开发完成,所以也就有点赶,但是却遇到了一个比较奇怪的Bug,导致了任务比预计的延迟了几个小时,对此深表遗憾,所以利用国 ...

  5. js事件捕获,事件冒泡,事件委托以及DOM事件流

    一:DOM事件流: 事件流是从页面接收事件的顺序,DOM2级事件规定事件流包括三个阶段: ①事件捕获阶段:用意在于事件达到目标之前捕获它,在事件捕获阶段事件流模型:document→html→body ...

  6. Android上的事件流操作数据库

    最近在浏览某篇有关事件流的文章时,里面提到了数据的流处理,兴趣来了,就想看看能否在Android端实现一个. 根据文章的介绍,将每次数据的变更事件,像是插入,删除或者更新等,记为一个不可变的事件,让数 ...

  7. JavaScript事件流

    什么是JS事件流 早期的IE事件传播方向为由上至下,即从document逐级向下传播到目标元素:而Netscape公司的Netscape Navigator则是朝相反的方向传播, 也就是从目标元素开始 ...

  8. [Effective Java]第二章 创建和销毁对象

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  9. JavaScript DOM高级程序设计 4.3控制事件流和注册事件侦听器--我要坚持到底!

    一.事件流 我们通过下面一个实例,进行说明. <body> <h1>Event Flow</h1> <ul id="nav"> &l ...

随机推荐

  1. Python学习 :装饰器

    装饰器(函数) 装饰器作为一个函数,可以为其他函数在不修改原函数代码的前提下添加新的功能 装饰器的返回值是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权限校验等 ...

  2. 让pandas的输出结果中显示全部数据

    import pandas as pd pd.set_option('display.max_columns', 1000) pd.set_option('display.width', 1000) ...

  3. PC环境搭建——虚拟机配置双网卡

    Vmware虚拟机三种网络模式详解 TCP/IP协议四层模型: 应用层 传输层 网络层 物理接口 桥接模式时,主机和虚拟机在同一个网段,之间可以相互访问 NAT模式时,主机和虚拟机不在同一网段,之间通 ...

  4. java语言描述 用抽象类模拟咖啡机的工作

    import java.util.Scanner; class Test { public static void main(String[] args) { coffee per = new cof ...

  5. Milking Order

    Milking Order 题意:给出m个描述状态,其中包含若干个边的关系,问最多能取x (x<=m)个状态,使得形成的图没有环.就是说取x个状态,用状态中的关系建边,其中不能有环. 题解:最大 ...

  6. [Real World Haskell翻译]第22章 扩展示例:Web客户端编程

    第22章 扩展示例:Web客户端编程 至此,您已经看到了如何与数据库交互,解析一些数据,以及处理错误.现在让我们更进了一步,引入Web客户端库的组合. 在本章,我们将开发一个真正的应用程序:一个播客下 ...

  7. docker (2) 通用/镜像命令

    原文:docker (2) 通用/镜像命令 Docker 的常用命令: (1)Docker  help 命令: 可以查看有关docker的所有操作命令: (2)docker COMMAND -–hel ...

  8. JDK核心源码(2)

    Java的基础知识有很多,但是我认为最基础的知识应该要属jdk的基础代码, jdk的基础代码里面,有分了很多基础模块,其中又属jdk包下面的lang包最为基础. 我们下面将总结和分析一下lang包下面 ...

  9. JavaScript---设计模式之职责链模式

    概念 职责链模式是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止. 链中收到请求的对象要么亲自处理它,要 ...

  10. 创龙DSP6748开发板上电测试-第一篇

    1. 创龙DSP6748开发板测试.2980元的售价很高,我估计新的1200元比较合适,当然创龙定价是按照供需关系的.仿真器XDS100V2卖598元,真是狮子大张口. 2. 上电是5V-2A的电源. ...