qt學習記錄-1

信號與槽

  • connect函數參數中‘槽函數實參’沒有聲明爲slots時,編譯不會報錯,但是也不會起作用(被執行)。
  • 注意qt4和qt5兩種版本下connect函數中信號和槽函數的形參不同。
  • 使用qt5語法時,若信號存在重載,則connect函數編譯時會報錯,不能準確的與槽函數(形參格式)相匹配!這時要麼用qt4形式,要麼通過static_cast方法進行數據類型裝換,如:
    在這裏插入圖片描述
    (將QButtonGroup::buttonClicked強制裝換爲形參是int的那個)
    參考:https://blog.csdn.net/f_zyj/article/details/82018147
  • C++中"A:: "的意思:指向類A中任意元素的指針(變量、方法),如:
    int A::
    point_i2,表示point_i2是一個指向類A中int變量的指針;
    如果A::fun存在重載,則:static_cast<void (A:😗)(int)>(&fun):表示將fun函數指針強制裝換爲類A中形參格式爲int的那個重載函數的函數指針。(有歧義,待改正)
  • qt中使用資源文件時,如果編譯提示:
    在這裏插入圖片描述
    原因:一般由於文件資源路徑改動後導致。
    解決辦法:將工程目錄下對應工程的Debug文件刪除,重新編譯工程即可。
  • 在爲button和form設置icon時,icon的路徑沒有問題,但就是不顯示icon內容,刪除debug文件夾也無效,後來在qt creater中刪除*.qrc資源樹下導入的文件,重新添加後恢復正常,不知道以後會不會再遇到!
  • C++中靜態成員(變量和方法)的作用、理解及其使用(不需要依賴具體的對象)

創建對象:使用和不使用new

  1. 不使用new關鍵字(QLabel label1;):新建的對象位於棧中,屬於局部變量,在函數結束後被自動銷燬;
  2. 使用new關鍵字(QLabel *label2=new QLabel;):新建的對象位於堆中,生命週期通常比棧中變量長,需要手動釋放。
  3. 下面通過4種形式分別測試在不同位置創建QPushButton對象,對應的現象:
  • 在類的構造函數中不使用new創建:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  MainWindow w;

//  QPushButton btn1("btn1", &w);
//  QPushButton *btn2=new QPushButton("btn2", &w);

  w.show();

  return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  //

    QPushButton btn1("btn1", this);
//  QPushButton *btn2=new QPushButton("btn2", this);

}
MainWindow::~MainWindow()
{
  delete ui;
}

運行結果:按鈕未顯示
在這裏插入圖片描述

  • 在類的構造函數中使用new創建:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  MainWindow w;

//  QPushButton btn1("btn1", &w);
//  QPushButton *btn2=new QPushButton("btn2", &w);

  w.show();

  return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  //

//    QPushButton btn1("btn1", this);
  QPushButton *btn2=new QPushButton("btn2", this);

}
MainWindow::~MainWindow()
{
  delete ui;
}

運行結果:按鈕正常顯示
在這裏插入圖片描述

  • 在main函數中不使用new創建:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  MainWindow w;

  QPushButton btn1("btn1", &w);
//  QPushButton *btn2=new QPushButton("btn2", &w);

  w.show();

  return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  //

//  QPushButton btn1("btn1", this);
//  QPushButton *btn2=new QPushButton("btn2", this);

}
MainWindow::~MainWindow()
{
  delete ui;
}

運行結果:按鈕正常顯示
在這裏插入圖片描述

  • 在main函數中使用new創建:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  MainWindow w;

//  QPushButton btn1("btn1", &w);
  QPushButton *btn2=new QPushButton("btn2", &w);

  w.show();

  return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  //

//  QPushButton btn1("btn1", this);
//  QPushButton *btn2=new QPushButton("btn2", this);

}
MainWindow::~MainWindow()
{
  delete ui;
}

運行結果:按鈕正常顯示
在這裏插入圖片描述
經測試發現:通過new關鍵字在堆上創建對象時,無論是在類的函數中還是在main函數中,都可以正常顯示;不使用new關鍵字在類的函數中創建對象時,對象不可見,因爲在類函數執行結束後,對象也被銷燬;不使用new關鍵字在main函數中創建對象時,對象也可見,因爲當前對象的聲明週期是在main函數內,而main函數因爲return a.exec();的存在而不會退出;最後我們再做個測試:

  • 在main函數中不使用new創建,但放置在函數體中:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  MainWindow w;

  do{
      QPushButton btn1("btn1", &w);
    }while(0);
//  QPushButton *btn2=new QPushButton("btn2", &w);

  w.show();

  return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  //

//  QPushButton btn1("btn1", this);
//  QPushButton *btn2=new QPushButton("btn2", this);

}
MainWindow::~MainWindow()
{
  delete ui;
}

運行結果:按鈕不顯示
在這裏插入圖片描述
和預料中一樣,對象在do…while的花括號結束後就被銷燬了,所以不可見。

創建對象但不指定parent時的現象

#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  MainWindow w;

//  do{
//      QPushButton btn1("btn1", &w);
//    }while(0);

  QPushButton *btn2=new QPushButton("btn2", &w);
  QPushButton *btn3=new QPushButton("btn3");
  btn3->show();
  w.show();

  return a.exec();
}

結果:
在這裏插入圖片描述

  • 這兩個窗體是不是模態的,相互可以疊加,各自的按鈕也可以單獨按下;
  • 關閉其中任意一個,程序都不會結束,除非兩個窗體都關閉。
    待研究。。。

父、子對象析構順序測試

  1. 先在棧中定義子對象,再定義父對象,子對象再綁定父對象:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QMenuBar>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  QPushButton btn1("btn1");
//  QPushButton *btn3=new QPushButton("btn3");

  MainWindow w;

  btn1.setParent(&w);
//  btn3->setParent(&w);

  w.show();

  return a.exec();
}

關閉窗口後,程序崩潰。

  1. 先定義父對象,再在棧中定義子對象,子對象再綁定父對象:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QMenuBar>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

//  QPushButton *btn3=new QPushButton("btn3");

  MainWindow w;

  QPushButton btn1("btn1");
  btn1.setParent(&w);
//  btn3->setParent(&w);

  w.show();

  return a.exec();
}

關閉窗口後,程序正常結束。

  1. 先在堆中定義子對象,再定義父對象,子對象再綁定父對象:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QMenuBar>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

//  QPushButton btn1("btn1");
  QPushButton *btn3=new QPushButton("btn3");

  MainWindow w;

//  btn1.setParent(&w);
  btn3->setParent(&w);

  w.show();

  return a.exec();
}

關閉窗口後,程序正常結束。

  1. 先定義父對象,再在堆中定義子對象,子對象再綁定父對象:
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QMenuBar>

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);

//  QPushButton btn1("btn1");

  MainWindow w;

//  btn1.setParent(&w);

  QPushButton *btn3=new QPushButton("btn3");
  btn3->setParent(&w);

  w.show();

  return a.exec();
}

關閉窗口後,程序正常結束。
分析(局部對象的析構順序應該按照其創建順序的相反過程):
1. 在堆上創建的對象不論創建順序前後,程序都會正常結束;
2. 如果在棧上創建的子對象比父對象先創建,在父對象先調用析構函數且釋放其所有子對象後,子對象的析構函數再次被調用,所以造成程序異常崩潰;
3. 在棧上創建的子對象在父對象之後創建,則會先調用子對象的析構函數將其從父對象 window 的子對象列表中刪除,然後纔會再調用 window 的析構函數,程序正常結束。
結論:

  1. 在棧上創建子對象時就綁定父對象,在父對象還不存在時編譯器會報錯,起到提示作用,避免程序運行後才感知到錯誤。
  2. 儘量在堆上創建子對象,可以避免定義的順序問題。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章