目录
一、什么是QT?
Qt是一个跨平台的C++图形用户界面应用程序框架。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。 Qt不仅限于GUI开发,还能进行多线程、数据库、图像处理、音视频处理、网络通信与文件IO等功能的开发。Qt是一个面向对象的框架,使用特殊的代码生成工具扩展成为原对象编译器,很容易扩展,并且允许真正的组件编程。
1、发展史
1991 奇趣科技
2、Qt的特征
- (1)面向对象
- (2)控件间的相互通信
- (3)友好的联机帮助
- (4)用户自定义
3、优点
- 跨平台,几乎支持所有的平台
- 接口简单,容易上手,学习QT框架对学习其他框架有参考意义。
- 一定程度上简化了内存回收机制
- 开发效率高,能够快速的构建应用程序。
- 有很好的社区氛围,市场份额在缓慢上升。
- 可以进行嵌入式开发。
4、QtCreate是什么?
对应的Qt SDK
5、Qt的应用场景有哪些?
桌面应用程序开发:QT可以用于开发各种类型的桌面应用程序,包括办公软件、图形编辑器、音频/视频播放器等。
移动应用程序开发:QT提供了移动应用程序开发的框架,可以用于开发Android和iOS平台上的应用程序。
嵌入式应用程序开发:QT支持嵌入式系统上的应用程序开发,可以用于开发嵌入式设备的控制界面、工业自动化系统等
二、QT---记事本文件编译
利用记事本写qt程序
1、QT编译的过程是怎么样的?
具体过程看这篇博客,我没有成功实现。
2、简单控件函数的编写
3、控件布局
打开QT命令窗口
查看文件
创建工程文件
没有成功,因为环境变量没有修改到
修改环境变量后,编译成功
qmake -project生成工程文件(.pro)
qmake生成Makefile
输入mingw32-make进行编译,生成(.exe)文件,发现出现报错
安装:Mingw的安装包,例如 codeblocks-20.03mingw-32bit-setup.exe
windows下使用Mingw执行make编译 - svchao - 博客园 (cnblogs.com)
问题未解决,以上只是体验Qt编译的过程,后续代码都是用Qtcreat编程。
三、Qtcreat编程
1、创建第一个工程
点击创建项目后,选择项目路径以及 给项目起名称
名称 - 不能有中文 不能有空格
路径 - 不能有中文路径
默认创建有窗口类,基类有三种选择: QWidget 、QMainWindow、QDialog
Qwight是父类,QmainWindow和Qdialog是子类。
main函数
#include "widget.h"
#include <QApplication>
//main程序入口 argc命令行变量的数量 argv命令行变量的数组
int main(int argc, char *argv[])
{ //a应用程序对象,在Qt中,应用程序对象,有且仅有一个
QApplication a(argc, argv);
//窗口对象 Widget父类 ->QWight
Widget w;
//窗口对象,默认不会显示,必须要调用show方法显示窗口
w.show();
//让应用程序对象进入消息循环
//让代码阻塞到这一行
return a.exec();
}
2、添加到版本控制系统是什么?
多人做项目时候才用到,svn、vss、git;
其他人协助编写他人的项目时,需要update。
3、文件后缀的含义
.pro 工程文件 .cpp 源文件 .h 头文件
argc命令行变量的数量 argv命令行变量的数组
4、pro文件解释
QT += core gui Qt包含的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于4版本以上 包含 widget模块
TARGET = 01_FirstProject //目标 生成的.exe程序的名称
TEMPLATE = app //模板 应用程序模板 Application
SOURCES += main.cpp\ //源文件
mywidget.cpp
HEADERS += mywidget.h //头文件
四、Qt的命名规范和快捷键
1、命名规范
- 类名 : 首字母大写,单词与单词之间首字母大写
- 函数名 : 变量名称 首字母小写,单词和单词之间首字母大写
2、快捷键
注释 ctrl + /
运行 ctrl + r
编译 ctrl + b
字体的缩放 ctrl + 鼠标滚轮
查找 ctrl + f
整行移动 ctrl + shift +↑或者↓
帮助文档 F1
自动对齐 ctrl + i
同名之间的.h和.cpp切换 F4
使用帮助文档 :
- 第一种方式 F1
- 第二种 左侧按钮
- 第三种 D:\QT\QT5.14.2\5.14.2\mingw73_32\bin
- 第二种 左侧按钮
五、QpushButton创建
1、了解QPushButton类
头文件: include <QPushButton>
所属模块: widgets
QpushButton的父类: QabstractButton
子类: QCommandLinkButton
2、按钮控件常用的API
- 创建按键 QpushButton * btn = new QpushButton
- 创建父亲 setParent(this)
- 设置文本 setText(“文字”)
- 设置位置 move(宽,高)
- 创新指定窗口大小 resize
- 设置窗口标题 setWindowTitle
- 设置窗口固定大小 setFixedSize
- 设置按钮的窗口大小 btn->resize
下面是创建一个按键的例子:
如果中文显示不正常,修改默认编码为UTF-8:
widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <pushbutton.h>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//创建一个按钮
QPushButton * btn =new QPushButton;
btn->show();//show以顶层方式弹出控件
//目的是让btn对象 依赖在Widget窗口中
btn->setParent(this);
//显示文本
btn->setText("第一个按钮");
//移动btn1按钮
btn->move(200,100);
//创建第二个按钮 按照控件的大小创建窗口
QPushButton * btn2 = new QPushButton("第二个按钮",this);
//移动btn2按钮
btn2->move(100,100);
//按钮设置窗口大小
btn2->resize(50,50);
//重置窗口的大小
resize(600,400);
//设置固定的窗口大小
setFixedSize(600,400);
//设置窗口标题
setWindowTitle("第一个窗口");
//创建一个自己按钮的对象
PushButton * Btn = new PushButton;
Btn->setText("我自己的按钮");
Btn->move(300,100);
Btn->setParent(this); //设置到对象数中
//需求 点击我的按钮 关闭窗口
connect(btn,)
}
Widget::~Widget()
{
delete ui;
}
六、对象数
1、认识析构和构造的过程
从上到下做构造,从下到上做释放的过程
验证释放的过程:
2、在文件中创建一个文件(自己的类头文件)
取名为 PushButton
在PushButton.h中修改继承对象,
在.cpp文件中将QWidget(parent)修改为QPushButton(parent)
3、在析构函数中编写打印的信息,便于验证析构的顺序
#include "pushbutton.h"
#include <QDebug> //用于打印信息
PushButton::PushButton(QWidget *parent) : QPushButton(parent)
{
qDebug() << "我的按钮类析构调用";
}
PushButton::~PushButton() //析构
{
qDebug() << "我的按钮类析构调用";
}
4、运行工程
当关闭窗口
七、Qt中的坐标系
坐标体系:
以左上角为原点(0,0),x向右增加,y向下增加。
对于嵌套窗口,其坐标是相对于父窗口来说的。
八、信号与槽(重点)
人 ---> 摩擦 ----> 神灯 ----> 出灯神
按钮 ----> 点击 -----> 窗口 ----> 关闭
connect(信号发送者,发送的具体信号,信号的接收者,信号的处理(槽))
1、connect函数:
信号的发送者 ---按钮
QPushButton
信号的发送信号 ---点击
clicked
信号的接收者 --- 窗口
Widght
信号的槽,找到按钮的父类的槽函数(Public Slots)
close
信号槽的优点:松散耦合,信号发送端 和接收端 本身是没有关联的,通过connect连接 将两端 耦合在一起
close()为关闭功能
//参数1 信号的发送者 参数2 发送的信号(函数的地址) 参数3 信号的接收者 参数4 处理的槽
connect(Btn,&QPushButton::clicked,this,&Widget::close);
2、自定义的信号和槽
新建一个工程
选择基类为Widght
模拟需求:
首先创建一个新文件
创建Teacher的基类,因为Teacher不算一个按钮,创建父类选择最高的基类QObject,创建出来之后,放在树上就会自动释放,所以我们不用管它释放的操作。
创建Student类,父类选择QObject
默认生成头文件的代码中就会有一个自定义信号的位置
//自定义信号 写到signals下
//自定义信号的写法 没有返回值 返回值是void 在信号里面只需要声明 不需要实现
//可以有参数 可以重载
void hungry();
Student.h写槽函数写在public下
(早期Qt版本必须要写public slots下,高版本可以写在public或者全局下)
在Student.h作声明后,也需要在student.cpp下实现,函数类外实现加作用域
接下来在widget.h文件中声明这两个对象
在私有成员下,构建两个指针
在Widgt.cpp文件下,创建两个对象
//创建一个老师的对象
this -> tc = new Teacher(this); //初始化 ,也可以指定一个父亲 相当于放在了对象树上,不用管理它的释放操作
//创建一个学生的对象
this -> yzl = new Student(this);
将两个对象进行连接,使用到connect函数
//老师饿了 学生请客
connect(tc,&Teacher::hungry,yzl,&Student::treat);
运行代码后,没有打印出老师饿了,原因是还有一个前提条件:下课后
在Widgt.h中创建下课后的方法:
在Widght.cpp中实现这个方法
但是没有打印老师饿了的信息,原因是只是写了触发函数,没有调用该方法。
调用下课方法:
可以看到,老师饿了的信息已经打印出来了。
注意:需要先连接老师和学生两个对象,再调用下课方法,学生才会响应信息。
//老师饿了 学生请客
connect(tc,&Teacher::hungry,yzl,&Student::treat);
//调用下课方法
classIsOver();
自定义信号与槽总结
1、自定义信号:
写到signals下 返回void 需要声明 不需要实现 可以有参数 可以重载
2、自定义槽函数:
写到public slot下或者全局函数 返回void 需要声明 也需要实现 可以有参数 可以重载
3、触发自定义信号
触发关键字 emit
3、自定义信号与槽发送重载的解决
构建重载函数:
在student.h的公共成员里声明
在teacher.h的公共成员里声明
解决方法:
需要利用函数指针,明确指向函数的地址
函数返回值类型 (作用域::*指针变量名)(函数参数列表)
在声明一个成员函数的函数地址的时候,我们要把成员函数的作用域放到指针函数变量名的前面,目的是告诉编译器,这是该作用域下函数的函数指针,因为构建的Teacher和Student不是全局函数,是成员函数,所以说要把它的作用域加上,编译器才能设别到这个函数的指针。
//连接带参数的 信号和槽
//地址可以用 指针-> 地址
// 函数指针 -> 函数地址
void (Teacher::*teacherSignal)(QString) = &Teacher::hungry;
void(Student::*studentSlot)(QString) = &Student::treat;
connect(tc,teacherSignal,yzl,studentSlot);
//下课函数 调用后 触发老师饿了的信号
void Widget::classIsOver()
{
//关键字
// emit tc -> hungry();
emit tc->hungry("宫保鸡丁");
}
打印的宫保鸡丁带引号问题的解决
请老师吃饭,老师要吃 属于char *类型
宫保鸡丁 属于QString类型
将 QString 转成 char *类型 即可,打开帮助文档查找QByteArray,找到Public Functions(公共功能)
在student.cpp中修改
void Student::treat(QString foodName)
{
// qDebug()<<"请老师吃饭,老师要吃"<<foodName;
// QString -> char * 先转成QByteArray 再转成char *
qDebug()<<"请老师吃饭,老师要吃"<<foodName.toUtf8().data();
}
编译运行
九、按钮触发下课
按钮 ---> 点击 ----> 窗口 ----> 下课
//连接带参数的 信号和槽
//地址可以用 指针-> 地址
// 函数指针 -> 函数地址
void (Teacher::*teacherSignal)(QString) = &Teacher::hungry;
void(Student::*studentSlot)(QString) = &Student::treat;
connect(tc,teacherSignal,yzl,studentSlot);
//调用下课方法
// classIsOver();
//点击 下课按钮 ,再触发下课
QPushButton * btn = new QPushButton("下课",this);
//设置窗口大小
this ->resize(600,400);
//连接
connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);//this指向Widgt
点击下课,触发下课,老师饿了,学生请客吃饭
十、信号连接信号
void Teacher::hungry_printf()
{
qDebug()<<"我饿了" ;
}
//无参信号和槽的连接
void (Teacher::*teacherSignal2)(void) = &Teacher::hungry;
void(Teacher::*teacherSignal_printf)(void) = &Teacher::hungry_printf;//公共成员函数--->打印我饿了
void(Student::*studentSlot2)(void) = &Student::treat;
connect(tc,teacherSignal2,tc,teacherSignal_printf);//老师和饿了信号连接,老师自己接收饿了的信息,打印我饿了
connect(tc,teacherSignal2,yzl,studentSlot2); //老师和饿了信号连接 学生和请客吃饭信号连接
//信号连接信号
connect(btn,&QPushButton::clicked,tc,teacherSignal2);//点击按钮 ---> 老师饿了
//断开信号
// disconnect(tc,teacherSignal2,yzl,studentSlot2);
编译运行,点击下课
断开信号连接
//断开信号
disconnect(tc,teacherSignal2,yzl,studentSlot2);
十一、学习总结
通过此次学习,明白了QPushButton类的父类和子类的关系,学会了如何使用Qt按钮控件常用的API,了解了Qt工程创建的注意事项,QWidgt界面的概念,对象数的概念以及析构和构造的过程,Qt中坐标系的体系等等内容。通过信号和槽的学习,学会了connect连接函数,理解了将发送者和发送信号连接在一起,将接收者和槽连接在一起的过程,学会了利用Qt帮助文档找信号函数和槽函数。