QT传智版笔记-day01
#include "mainwindow.h"
#include <QApplication>//包含一个应用程序的头文件
//main程序入口 argc 命令行变量的数量 argv命令行变量的数组
//一个程序界面鼠标点了 键盘键入的数据都是由下面这两个参数进行传入的
int main(int argc, char *argv[])
{
//接收到界面的鼠标 键盘键入命令后将这些命令放入这个方法的参数中
//a就是应用程序对象 在QT中,应用程序对象有且只有一个
QApplication a(argc, argv);
//窗口对象 myWidget父类 ->QWidget
MainWindow w;
//窗口对象,默认不会显示,必须要调用show方法显示窗口
//当代码阻塞到这里
w.show();
//让应用程序对象进入消息循环机制 差不多就是个死循环,直到
return a.exec();
}
QT += core gui QT包含的模块 core:核心 gui:图形
greaterThan(QT_MAJOR_VERSION,4): QT += widgets //大于4版本以上 包含widget模块
TARGET = 01_FirstProject //目标 生成.exe程序的名称
TEMPLATE = app //模板 应用程序模板 Application
SOURCES += main.cpp\ //源文件
mywidget.cpp
HEADERS += mywidget.h //头文件
构造函数与析构函数
特殊函数:由系统自动指向,在程序中不可显式地调用它们。
- 构造函数的作用:建立对象时对对象的数据成员进行初始化
- 析构函数的作用:对象生命周期结束时回收对象
- 构造函数:对象的初始化
- 析构函数:回收/撤销对象 回收分配的空间
- 构造函数和析构函数是一一对应的
构造函数:对象初始化
- 构造函数的作用:建立对象时对对象的数据成员进行初始化
- 是与类同名的特殊成员函数
- 没有返回值
- 可以有多个,带参数及无参数均可。
- 构造函数没有返回值但是不需要写void
复习重载:同名的函数 参数不同叫做重载。
无参构造函数 对象的初始化
例10.2 用class定义一个学生类,并在主函数中定义类的对象进行调用测试。
class student
{
private:
int no;
string name;
float score[3];
public:
student(); //构造函数
void display();//定义略
};
student :: student() //:: 这两个冒号表示 前面的student这个类 归属于后面的student()函数
{
no = 0;
name="null";
for(int i = 0;i<3;i++)
score[i] = 0;
};
int main(){
student s1;
s1.display();
return 0;
};
class student{
private:
int no;
string name;
float score[3];
public:
student(int n,string na,float s[3]);
void display();//定义略
};
student :: student(int n,char na[20],float s[3]){
no=n;
name = na;
for(int i = 0;i<3;i++)
score[i]=s[i];
}
int main(){
float s[3]={93,89,87};
student s1(100,"zhou",s);
s1.display();
return 0;
}
默认构造函数 对象的初始化
- C++ 规定,每个类必须有构造函数
- 如果一个类没有定义任何构造函数,在需要时编译器将会为它生成一个无参的,函数体为空的默认构造函数
- 默认构造函数只是在形式上保证创建对象时必须有构造函数。
- 一旦写了一个构造函数,系统就不再提供默认的构造函数
构造函数的特点
- 构造函数与类同名
- 构造函数没有返回类型
- 构造函数由系统自动调用,不允许在程序中显式调用。
- 构造函数可以被重载,即一个类可以定义多个参数或参数类型不同的构造函数
class student{
private:
int no;
string name;
float score[3];
public:
studnet();//无参
student(int n,string na,float s[3]);//有参
void display();
};
析构函数-回收/撤销对象
- 析构函数主要用于对象生命周期结束时回收对象
- 与类同名,在其前面加上字符"~"
- 没有返回值
- 在一个类当中只有一个,无参
//类内声明:
class X{
......
~X();
......
};
//类内定义
class X{
......
~X(){}
......
};
析构应用
class student //定义学生类,有构造函数和析构函数
{
private:
int no;
string name;
float score[3];
public:
student();//无参构造函数,类外定义
student(int n,string na,float s[3]);//有参构造函数,类外定义
~student()
{cout<<"destroy.\n"}//析构函数,可以在类内定义
void display();
};
//对无参构造函数的定义
student :: student(){
no = 0;
name = "null";
for(int i = 0; i<3; i++)score[i]=0;
}
//对有参构造函数的定义
student :: student(int n,string na,float s[3]){
no = 0;
name = "null";
for(int i = 0; i<3; i++)score[i]=s[i];
}
//对display函数的定义
//信息的输出 把display放在类的外面 放在类的外面需要指明它的归属程度
void student :: display() //类名写在哪里才能表明函数归属于哪一个类
{
cout<<no<<"\t"<<name<<"\t";
for(int i = 0; i<3;i++)
cout<<score[i]<<"\t";
cout<<end1;
}
例10.2用class定义一个学生类,并在主函数中定义类的对象进行调用测试
int main(){
float s[3] = {93,89,87};
student s1,s2(100,"zhou",s);
s1.display();
s2.display();
return 0;
}
默认析构函数
- 如果一个类没有定义任何析构函数,系统会为它生成一个默认析构函数。
- 对应大多数类,默认析构函数能够满足要求。
- 只有在一个对象完成其操作之前需要做一些内部处理时,才显示地定义析构函数
class X{
......
~X(){}
......
};
student :: ~student(){
cout<<"destroy\n";
}
第一个按钮
#include "mywidget.h"
#include <QPushButton> //按钮控件的头文件
//命名规范
//类名 首字母大写,单词和单词之间首字母大写
//函数名 变量名称 首字母小写,单词和单词之间首字母大写
//快捷键
//注释 ctrl + /
//运行 ctrl + r
//编译 ctrl + b
//字体缩放 ctrl + 鼠标滚轮
//查找 ctrl + f
//整行移动 ctrl + shift + ↑ 或者 ↓
//帮助文档 F1
//自动对齐 ctrl = i;
//同名之间的.h 和 .cpp切换 F4
//帮助文档 第一种方式F1
// 第二种方式 左侧按钮
// 第三种方式 ?:\Qt\qtxx.x.x\x.x\mingw49_32\bin
myWidget::myWidget(QWidget *parent)
: QWidget(parent) //初始化列表
{
//创建一个按钮 先引入按钮头文件
QPushButton * btn = new QPushButton;
//注意:show默认是在顶层窗口展示,也就是一个独立的自己的窗口,要归属于另一个窗口需要进行
// btn->show();//show以顶层方式弹出窗口控件
//需求是让btn对象,依赖在 myWidget窗口中
//设置”父亲“ 把父亲myWidget的指针放入参数中用this this指向当前对象的指针
btn->setParent(this);
//显示文本
btn->setText("第一个按钮");
//创建第二个按钮 按照空间的大小创建窗口 而且默认会覆盖上面的按钮 需要移动位置
QPushButton * btn2 = new QPushButton("第二个按钮",this);//效果与上面的相同
//移动btn2按钮
btn2->move(100,100);
//重置窗口大小 resize在stl中是重置内存大小
resize(600,400);
//对按钮大小进行调整
btn2->resize(50,50);
//设置窗口标题
setWindowTitle("第一个窗口");//但是此时可以缩放窗口
setFixedSize(600,400);
}
myWidget::~myWidget()
{
}
对象树
在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释一下这个parent到底是干什么的。
-
QObject是以对象树的形式组指起来的。
- 当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是parent,也就是父对象指针。
这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
- 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意思上的父类!)
这种机制在GUI程序设计中相当有用。例如,一个按钮有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。这是合理的。
-
QWidget是能够在屏幕上显示一切组件的父类。
- QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件,因此,它会显示在父组件的坐标系中,被父组件的边界剪裁。例如用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
QT的窗口原点在 0.0点 不同引擎的窗口起始点是不一样的。
信号和槽
人 -----摩擦摩擦 ------ 神灯------ 出神灯
按钮 ------ 点击 ------ 窗口 ------ 关闭窗口
connect(信号的发送者,发送的具体信号,信号的接收者,信号的处理(槽))
信号槽的优点,松散耦合,信号发送端 和 接收端 本身是没有关联的,通过connect连接 将两端耦合在一起
//需求:点击我的按钮,关闭窗口
//参数1 信号的发送者 参数2 发送的信号(函数的地址) 参数3 信号的接收者 参数4 处理的槽函数
connect(myBtn,&QPushButton::clicked,this, &QWidget::close);
connect(myBtn,&MyPushButton::clicked,this, &myWidget::close);
拓展
1、信号是可以连接信号的
2、一个信号可以连接多个槽函数
3、多个信号,可以连接同一个槽函数
4、信号和槽的参数 必须类型一一对应
5、信号和槽的参数个数是不是要一致?信号的参数个数 可以多于槽函数的参数个数
利用QT4信号槽 连接无参版本
connect(zt,SIGNAL(hungry()),st,SLOT(treat()));
QT4版本有点:参数只管,缺点:类型不做检测
Lambda表达式
C++中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作,首先看一下Lambda表达式的基本构成:
[capture](parameter) mutable->return-type
{
statement
}
[函数对象参数] (操作符重载函数参数) mutable -> 返回值(函数体)
- 函数对象参数;
[],标识一个 Lambda的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些到定义Lamb大为止时Lambda所在作用范围内可见局部变量(包括Lambda所在类的this)。函数对象参数有一下形式:
- 空。没有使用任何函数对象参数
- =。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且时值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
- &。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。
- this。函数体内可以使用Lambda所在类中的成员变量。
- a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数时const的。要修改传递进来的a的拷贝,可以添加mutable修饰符
- &a。将a按引用进行传递。
- a,&b。将a按值进行传递,b按引用进行传递
- =,&a,&b 除a和b按引用进行传递外,其他参数都按值进行传递
- &,a,b。除a和b按值进行传递外,其他参数都按引用进行传递
操作符重载函数参数:
- 标识重载的()操作符的参数,没有参数时,这部分可以省略。参数可以通过值(如:(a,b)和按引用(如:(&a,&b)))两种方式进行传递
可修改标识符:
- mutable声明,这部分可以省略。按值传递函数对象参数时,加上mutable修饰后,可以修改按值传递进来的拷贝(注意时修改拷贝,而不是值本身)。
QPushButton*myBtn = new QPushButton(this);
QPushButton*myBtn2 = new QPushButton(this);
myBtn2->move(100,100);
int m = 10;
connect(myBtn,&QPushButton::clicked,this,[m]()mutable{m=100+10;qDebug() << m;});
connect(myBtn,&QpushButton::clicked,this,[=]() {qDebug() << m;});
qDebug() << m;
函数返回值;
->返回值类型,标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此编译器可以自动推断出返回值类型)时这部分可以省略。
时函数体:
{},标识函数的实现,这部分不能省略,但函数体可以为空