.pro文件
1 2 3 4 5 6 7 QT += core gui //包含的模块 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于Qt4版本 才包含widget模块 TARGET = QtFirst //应用程序名 生成的.exe程序名称 TEMPLATE = app //模板类型 应用程序模板 SOURCES += main.cpp\ //源文件 mywidget.cpp HEADERS += mywidget.h //头文件
.pro就是工程文件(project),它是qmake自动生成的用于生产makefile的配置文件 。.pro文件的写法如下:
注释
从“#”开始,到这一行结束。
模板变量
告诉qmake为这个应用程序生成哪种makefile。下面是可供使用的选择:TEMPLATE = app
app -建立一个应用程序的makefile。这是默认值,所以如果模板没有被指定,这个将被使用。
lib - 建立一个库的makefile。
vcapp - 建立一个应用程序的VisualStudio项目文件。
vclib - 建立一个库的VisualStudio项目文件。
subdirs -这是一个特殊的模板,它可以创建一个能够进入特定目录并且为一个项目文件生成makefile并且为它调用make的makefile。
配置信息
CONFIG用来告诉qmake关于应用程序的配置信息。
CONFIG += c11 //使用c 11的特性
在这里使用“+=”,是因为我们添加我们的配置选项到任何一个已经存在中。这样做比使用“=”那样替换已经指定的所有选项更安全。
命名规范
类名:首字母 大小 单词和单词之间 首字母 大写
变量、函数名: 首字母小写 单词和单词之间 首字母 大写
快捷键
1 2 3 4 5 6 7 8 9 10 11 运行 ctrl + R 编译 ctrl + B 查询 ctrl + F 注释 ctrl + / 帮助 F1 字体缩放 ctrl + 鼠标滚轮 整行代码移动 ctrl + shift + ↑ ↓ 自动对齐 ctrl + i 同名之间的.h .cpp切换 F4 帮助文档 F1 左侧列表中按钮 C:\Qt\Qt5.6.0\5.6\mingw49_32\bin
mywidget.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> class MyWidget : public QWidget { Q_OBJECT //Q_OBJECT宏 支持信号和槽 public: MyWidget(QWidget *parent = 0); ~MyWidget(); }; #endif // MYWIDGET_H
mywidget.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #include "mywidget.h" #include <QPushButton> #include "mypushbutton.h" #include <QDebug> MyWidget::MyWidget(QWidget *parent) : QWidget(parent) { QPushButton * btn = new QPushButton; btn->setParent(this ); btn->setText("德玛西亚" ); QPushButton * btn2 = new QPushButton("第二个" ,this ); btn2->move(100 ,100 ); resize(600 ,400 ); setWindowTitle("第一个窗口" ); setFixedSize(600 ,400 ); MyPushButton * myBtn = new MyPushButton; myBtn->setParent(this ); myBtn->setText("我的按钮" ); myBtn->move( 300 ,200 ); connect( myBtn , &MyPushButton::clicked ,this , &MyWidget::close); } MyWidget::~MyWidget() { qDebug() << "MyWidget析构调用" ; }
mypushbutton.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #ifndef MYPUSHBUTTON_H #define MYPUSHBUTTON_H #include <QPushButton> class MyPushButton : public QPushButton{ Q_OBJECT public : explicit MyPushButton (QWidget *parent = 0 ) ; ~MyPushButton(); signals: public slots:}; #endif
mypushbutton.cpp
1 2 3 4 5 6 7 8 9 10 11 #include "mypushbutton.h" #include <QDebug> MyPushButton::MyPushButton(QWidget *parent) : QPushButton(parent) { } MyPushButton::~MyPushButton() { qDebug() << "MyPushButton的析构函数调用" ; }
对象模型(对象树)
一定程度上简化了内存回收机制
当创建的对象 指定的父亲是由QObject或者Object派生的类时候,这个对象被加载到对象树上,当窗口关闭掉时候,树上的对象也都会被释放掉
Qt中的坐标系
x以右侧为正
y以下侧为正
左上角是 0,0点
Qt中信号和槽基本使用

需求:点击按钮关闭窗口
连接 connect ( 信号的发送者,发送的信号,信号的接受者,处理的槽函数)
1 connect( myBtn , &MyPushButton::clicked ,this, &MyWidget::close);
当自定义插槽类有多个信号时,要使用函数指针来传递给connect函数,否则会出现歧义性,导致出错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #include "mywidget.h" #include <QPushButton> #include "mypushbutton.h" #include <QDebug> //命名规范 // 类名 首字母 大小 单词和单词之间 首字母 大写 // 变量、函数名 首字母小写 单词和单词之间 首字母 大写 //快捷键 // 运行 ctrl + R // 编译 ctrl + B // 查询 ctrl + F // 注释 ctrl + / // 帮助 F1 // 字体缩放 ctrl + 鼠标滚轮 // 整行代码移动 ctrl + shift + ↑ ↓ // 自动对齐 ctrl + i // 同名之间的.h .cpp切换 F4 // 帮助文档 F1 左侧列表中按钮 C:\Qt\Qt5.6.0\5.6\mingw49_32\bin MyWidget::MyWidget(QWidget *parent) : QWidget(parent) { //按钮 QPushButton * btn = new QPushButton; //btn->show(); //show用顶层方式弹出 //如果想显示到当前窗口中 ,需要做依赖 btn->setParent(this); //显示文本 btn->setText("德玛西亚"); //按钮2 QPushButton * btn2 = new QPushButton("第二个",this); //移动btn2 btn2->move(100,100); //重置窗口大小 resize(600,400); //按钮 可以重置大小吗? 可以 //btn->resize(300,200); //指定窗口标题 setWindowTitle("第一个窗口"); //设置窗口固定大小 setFixedSize(600,400); //创建自定义的按钮 MyPushButton * myBtn = new MyPushButton; myBtn->setParent(this); myBtn->setText("我的按钮"); myBtn->move( 300,200); //点击按钮 关闭窗口 //connect( 信号发送者,发送的信号,信号的接受者,处理的槽函数) //信号和槽 优点: 松散耦合 // connect(myBtn, &QPushButton::clicked , this, &QWidget::close ); connect( myBtn , &MyPushButton::clicked ,this, &MyWidget::close); } MyWidget::~MyWidget() { qDebug() << "MyWidget析构调用"; }
如果一个类找不到继承,可以选择QObject类
student.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #ifndef STUDENT_H #define STUDENT_H #include <QObject> class Student : public QObject { Q_OBJECT public: explicit Student(QObject *parent = 0); signals: //自定义槽函数 写到public slots Qt 5.0版本以上 可以写成全局函数或者public作用域下 或者 lambda表达式 public slots: //返回值是void //需要声明 也需要有实现 //可以有参数 可以发生重载 void treat(); void treat(QString foodName); }; #endif // STUDENT_H
student.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include "student.h" #include <QDebug> Student::Student(QObject *parent) : QObject(parent) { } void Student::treat() { qDebug() << "请老师吃饭"; } void Student::treat(QString foodName) { //如果打印QString类型的字符串会自带双引号,除非转换为chat * 类型 //QString 转 char * 通过.toUtf8转为 QByteArray 类型 通过 .data()转为 char * qDebug() << "请老师吃饭 , 老师要吃: " << foodName.toUtf8().data(); }
teacher.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #ifndef TEACHER_H #define TEACHER_H #include <QObject> class Teacher : public QObject { Q_OBJECT public: explicit Teacher(QObject *parent = 0); //自定义信号 写到signals下 signals: //返回值是void //只需要声明 不需要实现 //可以有参数 可以发生重载 void hungry(); void hungry( QString foodName); public slots: }; #endif // TEACHER_H
1 2 3 4 5 6 #include "teacher.h" Teacher::Teacher(QObject *parent) : QObject(parent) { }
widget.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include "student.h" #include "teacher.h" class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); Teacher * zt; Student * st; //下课 void classIsOver(); }; #endif // WIDGET_H
widget.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 #include "widget.h" #include <QPushButton> #include <QDebug> // Teacher老师类 // Student学生类 // 下课后 老师会触发一个 饿了 的信号 // 学生响应这个信号 并且 请老师吃饭 Widget::Widget(QWidget *parent) : QWidget(parent) { //参数带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); resize(600,400); void(Teacher:: *teacherSignal2)() = &Teacher::hungry; void(Student:: *studentSlot2)() = &Student::treat; connect(zt,teacherSignal2, st,studentSlot2); //1、信号是可以连接信号 connect(btn,&QPushButton::clicked,zt,teacherSignal2); //2、可以断开信号和槽 disconnect(zt,teacherSignal2, st,studentSlot2); //3、一个信号可以响应多个槽函数 //4、多个信号可以连接同一个槽函数 //5、信号和槽函数的参数类型 必须一一对应 // 信号的参数个数 可以多余槽函数的参数个数,反之不可以 , 参数类型要一一对应 //Qt4版本信号和槽写法 //利用Qt4版本连接有参信号和槽 //优势 :参数直观 //劣势 :参数类型不做匹配检测 // Qt4本质 SIGNAL("hungry(int)")SLOT("treat(QString)") // connect(zt, SIGNAL(hungry(QString)) , st , SLOT(treat(QString))); // classIsOver(); //[=] 函数体内可以使用Lambda所在作用范围内所有可见的局部变量 QPushButton * btn2 = new QPushButton("aaa",this); QPushButton * btn3 = new QPushButton("aaa",this); [=](){ btn2->setText("bbb"); btn3->setText("bbb"); }(); //最常用lambda使用 [=](){} QPushButton * btn4 = new QPushButton("aaa",this); btn4->move( 100, 0); //当进行信号和槽连接时候,控件内会进入一个锁的状态 connect(btn4,&QPushButton::clicked,this,[=](){ btn4->setText("bbb"); }); //加上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 = 20; qDebug() << m; }); connect(myBtn2,&QPushButton::clicked,this,[=] () { qDebug() << m; }); qDebug() << m; //-> 返回值类型 int num = [=]()->int{ return 1000; }(); qDebug() << "num = " << num ; //点击按钮 关闭窗口 connect(btn4,&QPushButton::clicked,[=](){ //this->close(); st->treat("宫保鸡丁"); }); } void Widget::classIsOver() { //触发自定义信号 // emit this->zt->hungry(); emit this->zt->hungry("宫保鸡丁"); } Widget::~Widget() { }
Lambda表达式
C++11中的Lambda表达式用于定义并创建匿名的函数对象 ,以简化编程工作。首先看一下Lambda表达式的基本构成:
1 2 3 4 5 6 [capture](parameters) mutable ->return-type { statement } [函数对象参数](操作符重载函数参数)mutable ->返回值{函数体}
函数对象参数有以下形式:
空。没有使用任何函数对象参数。
= :函数体内可以使用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修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)。
1 2 3 4 5 6 7 8 9 10 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 = 20; qDebug() << m; }); connect(myBtn2,&QPushButton::clicked,this,[=] () { qDebug() << m; }); qDebug() << m;
函数返回值;
->返回值类型,标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此时编译器可以自动推断出返回值类型)时,这部分可以省略。
{}是函数体;
{},标识函数的实现,这部分不能省略,但函数体可以为空。