QWidget一輩子,從建立到銷燬事件流

版權聲明:若無來源註明, Techie亮博客文章均爲原創。 轉載請以連接形式標明本文標題和地址:
本文標題:QWidget一輩子,從建立到銷燬事件流     本文地址: http://techieliang.com/2017/11/319/
代碼較多,此處顯示效果不佳,建議到原文地址查看

最近作UI,有多個窗口嵌套,且全部窗口均用了Layout佈局,當運行程序時,主窗口布局有效,而嵌套的窗口布局未生效。app

1. 構造函數Resize()

首先我想到的是,我設置了Layout,那麼他會自動調整大小,是否是在建立子窗口的時候並無獲取到此窗口在父類佈局中佔用的位置?那麼我在構造的時候分別設置每一個子窗口便可。ide

child_widget->Resize(this->XXXX->size());//XXXX是子窗口一個widget的區域,或者qstackedwidget等某個頁面的大小函數

使用上述相似的指令去從新設置,發現沒有任何效果。而根本緣由是構造函數中得到的Size()並不對,不是主窗口的真實尺寸。工具

2. 笨方法-QTimer()

因爲時間關係,使用了笨方法。不管如何最後構造完成之後確定窗口顯示了。。。。佈局

那麼創建一個定時器,構造的時候啓動定時器,鏈接到槽,而後timeout()之後執行Resize指令,而且stop Timer。。。測試

此方法確實解決了佈局適應的問題,可是創建一個timer,方法並不友好ui

3. QWidget構造到銷燬事件流分析

此處爲了方便,不對QWidget作範例分析,直接用QMainWindow作分析,QMainWindow是QWidget的子類。this

下面會詳細說明分析方法,若須要對QWidget或者其餘控件作分析,能夠仿照進行。spa

3.1. 實驗項目配置

直接新建一個Qt Widgets項目,爲了測試方便,我把默認的菜單欄、工具欄、狀態欄都取消了,只添加了一個QPushButton按鈕控件。orm

程序代碼以下:

*.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. }
  13. MainWindow::~MainWindow() {
  14. delete ui;
  15. }
  16. bool MainWindow::event(QEvent *event) {
  17. qDebug()<<event->type();
  18. QMainWindow::event(event);
  19. }

其實項目很簡單,就是直接重寫了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()
相關文章
相關標籤/搜索