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. 尽量在堆上创建子对象,可以避免定义的顺序问题。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章