目录
1、QT的概述:
(1)、QT概述
QT是一个跨平台的C++图形用户界面应用程序框架。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。
(2)、QT的优点
1、跨平台,几乎支持所有的平台。
2、接口简单,容易上手,学习QT框架对于学习其他框架有参考意义。
3、一定程度上简化了内存回收机制。
4、开发效率高,能够快速的构建应用程序。
5、有较好的社区氛围。
6、可以进行嵌入式开发。
2、创建QT项目:
(1)、使用向导创建
打开 Qt Creator 界面选择 New Project 或者选择菜单栏 【文件】 -【 新建文件或项目】 菜单项
(2)、创建QT界面项目
(3)、根据向导创建QT项目
填写项目名称及项目保存路径,注意:不能含有中文
注意:QT不支持中文显示,点击编辑---->select encoding----->UTF-8 ---->按编码保存(解决中文乱码问题)
3、第一个QT程序:
设置窗口标题,窗口大小,固定窗口大小。
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT //代表当前窗口支持信号和槽机制
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//设置窗口标题
this->setWindowTitle("QT开发");
//设置窗口大小
this->resize(800,600);
//固定窗口大小,不能修改
this->setFixedSize(800,600);
}
Widget::~Widget()
{
}
main.cpp
#include "widget.h"
//精简界面的头文件
#include <QApplication>
//基头文件
int main(int argc, char *argv[])
{
//创建一个应用程序对象。
QApplication a(argc, argv);
//实例化一个窗口对象
Widget w;
//显示窗口
w.show();
//主事件循环,等待用户操作界面事件
return a.exec();
}
运行结果:
4、按钮的创建和属性设置:
widget.cpp
#include "widget.h"
#include<QPushButton>
//加入按钮的头文件
Widget::Widget(QWidget *parent)
: QWidget(parent)
{ //创建一个标题
this->setWindowTitle("按钮事例");
//按钮的类名是QPushButton
//创建一个按钮的第一种方式
QPushButton *btn = new QPushButton("第一个按钮",this);
//创建一个按钮的第二种方式
QPushButton *btn1 = new QPushButton;
btn1->setParent(this);
btn1->setText("第二个按钮");
btn->move(100,0);
//向下改变y的大小,向右改变x的大小。
}
Widget::~Widget()
{
}
QT的窗口坐标体系:
运行结果:
5、对象树:
QObject是以对象树的形式组织起来的。Q_OBJECT出现在widget.h中代表当前窗口支持信号和槽机制。
1、当我们创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是parent,也就是父对象指针。这相当于,在创建QObject对象时,可以提供一个父对象,我们创建的这个QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
2、当父对象析构的时候,这个列表中所有的对象也会被析构。(这里的父对象不是继承意义上的父类)。
3、QT引入对象树的概念,在一定程度上解决了内存的问题。
4、先定义父对象再定义子对象,释放的时候如果释放了子对象再释放父对象会造成二次释放,从而导致程序崩溃。
6、信号和槽:
首先建立信号和槽的关系,信号发出后槽函数异步执行,通过connect函数建立链接。
信号:signals 特性:返回值void类型,可以有参数(可以重载) 信号没有函数体。
槽:public slots 特性: 返回值void类型,可以有参数(可以重载) 槽有函数体。
widget.h
#include "widget.h"
#include<QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//创建一个标题
this->setWindowTitle("信号和槽");
this->resize(300,300);
this->setFixedSize(300,300);
//创建一个按钮来发出关闭信号传给槽函数
QPushButton *btn = new QPushButton("关闭",this);
btn->move(100,100);
btn->resize(100,70);
btn->setFixedSize(100,70);
connect(btn,&QPushButton::clicked,this,&QWidget::close);
//btn属于QPushButton类发出信号clicked,传给this代表当前窗口
//窗口的类时QWidget,用close关闭槽函数接收。
// connect((btn,&QPushButton::pressed,this,&QWidget::close));
//pressed与clicked的区别,press鼠标点击就触发,clicked鼠标点击松开触发
}
Widget::~Widget()
{
}
7、自定义信号和槽:
(1)、无参--信号和槽
student,h
#ifndef STUDENT_H
#define STUDENT_H
#include<QObject>//支持信号和槽的头文件
#include<QDebug>//qt开发中常用输出的头文件
class Student:public QObject//继承父类QObject
{
Q_OBJECT//支持信号和槽
public:
explicit Student(QObject *parent = 0);
//构造函数,保证初始化的时候把QObject作为父对象
//explicit确保其他类型不会转换成QObject类型的指针。
public slots:
//槽函数的返回值void类型,可以有参数(可以重载),必须有函数体。
void treat()
{
qDebug()<<"请客吃饭"<<endl;
//qDebug()在QT中用作输出
}
};
#endif // STUDENT_H
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();
};
#endif // TEACHER_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"teacher.h"
#include"student.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
Teacher *tea;
Student *stu;
//定义俩个对象
};
#endif // WIDGET_H
student.cpp
#include "student.h"
Student::Student(QObject *parent)
{
}
teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent)
{
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include<QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QPushButton *btn = new QPushButton("请客",this);
//创建一个按钮,方便后面来学生请老师吃饭
this->tea= new Teacher(this);
this->stu = new Student(this);
//初始哈俩个对象,接受一个指向 QObject 对象的指针作为父对象。
//方便内存管理
this->resize(400,300);
//当前界面的大小
connect(tea,&Teacher::hungry,stu,&Student::treat);
//链接老师和学生,信号和槽链接
connect(btn,&QPushButton::clicked,tea,&Teacher::hungry);
//链接按钮触发老师,信号和信号链接
}
Widget::~Widget()
{
}
运行结果:
(2)、有参--信号和槽
信号和槽参数的要求:槽函数的形参不要大于所链接信号的参数个数,如有参数必须与信号的参数类型也要一致。
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include<QObject>//支持信号和槽的头文件
#include<QDebug>//qt开发中常用输出的头文件
class Student:public QObject//继承父类QObject
{
Q_OBJECT//支持信号和槽
public:
explicit Student(QObject *parent = 0);
//构造函数,保证初始化的时候把QObject作为父对象
//explicit确保其他类型不会转换成QObject类型的指针。
public slots:
//槽函数的返回值void类型,可以有参数(可以重载),必须有函数体。
void treat()
{
qDebug()<<"请客吃饭"<<endl;
//qDebug()在QT中用作输出
}
void treat(QString foodName)
{
//槽函数的参数个数必须<=信号的参数个数,参数类型也得一致
qDebug()<<"请老师吃:"<<foodName.toUtf8().data()<<endl;
//去掉 “” .toUtf8().data()
}
};
#endif // STUDENT_H
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:
//定义一个槽函数来接接收btn发送的信号
void classOver()
{
emit this->hungry("热干面");
//触发一个有参的信号
}
};
#endif // TEACHER_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"teacher.h"
#include"student.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
Teacher *tea;
Student *stu;
//定义俩个对象
};
#endif // WIDGET_H
student.cpp
#include "student.h"
Student::Student(QObject *parent)
{
}
teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent)
{
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include<QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QPushButton *btn = new QPushButton("请客",this);
//创建一个按钮,方便后面来学生请老师吃饭
this->tea= new Teacher(this);
this->stu = new Student(this);
//初始哈俩个对象,接受一个指向 QObject 对象的指针作为父对象。
//方便内存管理
this->resize(400,300);
//当前界面的大小
void(Teacher::*tea_p)(QString) = &Teacher::hungry;
void(Student::*stu_p)(QString) = &Student::treat;
//用指针指向有参的函数
connect(tea,tea_p,stu,stu_p);
//信号链接槽,teacher中触发了有参信号传递给student
connect(btn,&QPushButton::clicked,tea,&Teacher::classOver);
//信号可以链接槽
//btn发送信号到teacher的槽函数classover中,触发一个有参的信号
}
Widget::~Widget()
{
}
运行结果:
(3)、信号和槽的总结
1、信号的返回值类型void,可以有参数(可以重载),没有函数体,signals。
2、槽函数的返回值类型void,可以有参数(可以重载),有函数体,public slots。
3、信号可以连接信号。
4、槽函数的参数个数要小于等于信号的个数(参数类型属性与信号保持一致)。
5、一个信号可以连接多个槽函数(槽函数的执行顺便不定),多个信号可以连接同一个槽函数。
8、lambda表达式(匿名函数):
C++11中的lambda表达式用于定义并且创建匿名函数对象。
格式:[capture] (parameters) mutable ->return-type { }
捕获列表 参数 可变的返回值 函数体
1、【】不能访问lambda表达式外部变量。
2、【=】只能对外部变量进行读操作。
3、【a,b】能够对外部变量a,b读操作。
4、【&】能对外部表达式读写操作。
5、【a,&b】能对外部的a只读,b读写。
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
int a = 10;
int b = 20;
QPushButton *btn = new QPushButton("lambada表达式", this);
//lambda表达式把信号的接收者与槽函数合为一体
// connect(btn, &QPushButton::clicked, [&](bool ob){
// qDebug() << "读写成功" << endl;
// });
connect(btn, &QPushButton::clicked, [&]()mutable{
a = 100;
b = 200;
qDebug() << a +b << endl;
});
}