1 环境配置与Qt的安装
2 创建第一个Qt程序
- 点击创建项目后,选择项目路径以及 给项目起名称 名称
- 不能有中文 不能有空格 路径 - 不能有中文路径
- 默认创建有窗口类,myWidget,基类有三种选择: QWidget 、QMainWindow、QDialog
main函数
- QApplication a 应用程序对象,有且仅有一个
- myWidget w;实例化窗口对象
- w.show()调用show函数,显示窗口
- return a.exec() 让应用程序对象进入消息循环机制中,代码阻塞到当前行
3 按钮控件常用API
- 创建 QPushButton * btn = new QPushButton
- 设置父亲 setParent(this)
- 设置文本 setText(“文字”)
- 设置位置 move(宽,高)
- 重新指定窗口大小 resize
- 设置窗口标题 setWindowTitle
- 设置窗口固定大小 setFixedSize
4 对象树
当创建的对象在堆区时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,可以不用管理释放的操作,将对象会放入到对象树中。对象树一定程度上简化了内存回收机制
5 Qt中的坐标系
左上角为 0 , 0 点,x以右为正方向,y以下为正方向
6 信号和槽
信号和槽用于处理松散耦合
连接方式:connect
参数:
- 参数1:信号的发送者
- 参数2:信号
- 参数3:信号的接收者
- 参数4:槽函数
【自定义信号和槽】 - 自定义信号:返回值是void,只声明不实现,可以有参数,可以重载
- 自定义槽函数:返回值是void,需要声明也需要实现,可以有参数,可以重载,写在public slot下,在高版本中可以写在public
【案例】下课后,老师触发信号“饿了”,学生响应信号,请客吃饭。若信号中表明想吃什么,学生需要响应其需求。
学生类头文件student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = 0);
signals:
public slots:
//早期的Qt版本必须写到这里,高级版本可以写到public下,或者全局
//返回值:void,需要声明也需要实现
//可以有参数,可以重载
void treat();
void treat(QString foodName);
};
#endif // STUDENT_H
学生类源文件student.cpp
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::treat(){
qDebug() << "请老师吃饭";
}
void Student::treat(QString foodName){
qDebug() << "请老师吃饭,老师要吃" << foodName.toUtf8().data();
}
老师类头文件teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = 0);
signals:
//自定义信号区域
//返回值是void,只需要声明,不需要实现
//可以有参数,可以重载
void hungry();
void hungry(QString foodName);
public slots:
};
#endif // TEACHER_H
老师类源文件teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent) : QObject(parent)
{
}
主界面头文件widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <teacher.h>
#include <student.h>
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
Teacher * zt;
Student * st;
void classIsOver();
};
#endif // WIDGET_H
主界面文件widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
//Teacher 类 老师类
//Student 类 学生类
//情景:下课后,老师触发一个信号:饿了,学生响应信号:请客吃饭
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//创建一个老师的对象
this -> zt = new Teacher(this);
//创建一个学生对象
this -> st = new Student(this);
// //老师饿了,学生请客,连接
// connect(zt,&Teacher::hungry,st,&Student::treat);
// //下课
// classIsOver();
//函数指针
void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
void (Student:: *studentSlot)(QString) = &Student::treat;
//连接,宫保鸡丁
connect(zt,teacherSignal,st,studentSlot);
classIsOver();
//点击一个下课的按钮,触发下课
QPushButton *btn = new QPushButton("下课",this);
//重置窗口大小
this -> resize(600,400);
//点击按钮,触发下课
connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);
//无参信号槽连接
//函数指针
void (Teacher:: *teacherSignal2)(void) = &Teacher::hungry;
void (Student:: *studentSlot2)(void) = &Student::treat;
//老师信号连接槽
connect(zt,teacherSignal2,st,studentSlot2);
//按钮信号连接老师信号
connect(btn,&QPushButton::clicked,zt,teacherSignal2);
//断开连接
// disconnect(zt,teacherSignal2,st,studentSlot2);
}
void Widget::classIsOver()
{
//下课函数
// emit zt -> hungry();
// emit zt -> hungry("宫保鸡丁");
}
Widget::~Widget()
{
delete ui;
}
信号与槽拓展
- 信号可以连接信号
- 一个信号可以连接多个槽函数
- 多个信号可以连接同一个槽函数
- 信号和槽函数的参数 必须类型一一对应
- 信号和槽的参数个数是不是要一致?不是。信号的参数个数 ≥ 槽函数的参数个数 。但对应位置的数据类型一致
- 信号槽可以断开连接 disconnect
Qt4版本以前的信号和槽连接方式
信号函数:SIGNAL()
槽函数:SLOT()
优势:参数直观;缺点:编译器对类型不做检测
//Qt4版本连接
//优势:参数直观;缺点:编译器对类型不做检测
connect(zt,SIGNAL(hungry(),st,SLOT(treat());
Lambda表达式
早期的版本是c++11中才有Lambda表达式,使用时应该该项目.pro文件中加入
CONFIG += C++11
Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。
格式:
//匿名函数声明
[](){}
//声明后调用
[](){}();
① 函数对象参数
[],标识一个Lambda的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些到定义Lambda为止时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修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)。
信号和槽总结图