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;
}

信号与槽拓展

  1. 信号可以连接信号
  2. 一个信号可以连接多个槽函数
  3. 多个信号可以连接同一个槽函数
  4. 信号和槽函数的参数 必须类型一一对应
  5. 信号和槽的参数个数是不是要一致?不是。信号的参数个数 ≥ 槽函数的参数个数 。但对应位置的数据类型一致
  6. 信号槽可以断开连接 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修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)。

信号和槽总结图

QAT 创建 VF_QAT 创建 VF