1.下载和安装
QT下载
选择CN镜像下载即可。
2.创建项目
3.文件目录
main.app
#include "mywidget.h"
#include <QApplication>//包含一个应用程序类的头文件。
//argc命令行变量的数量,argv是命令行变量的数组
int main(int argc, char *argv[])
{
//a 应用程序对象 应用程序对象有且仅有一个
QApplication a(argc, argv);
//窗口对象 ->QWidget
myWidget w;
//窗口对象默认不会显示
//让代码阻塞到这行
w.show();
//让应用程序对象进入消息循环机制
return a.exec();
}
Project_01.pro
//包含模块
QT += core gui
//大于4版本,包含widgets模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
//源文件
SOURCES += \
main.cpp \
mywidget.cpp
//头文件
HEADERS += \
mywidget.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
class myWidget : public QWidget
{
//宏 允许类中使用信号和槽的机制
Q_OBJECT
public:
myWidget(QWidget *parent = nullptr);
~myWidget();
};
#endif // MYWIDGET_H
mywidget.cpp
#include "mywidget.h"
#include <QPushButton>
#include "mypushbutton.h"
#include <QDebug>
myWidget::myWidget(QWidget *parent)
: QWidget(parent)
{
//创建一个按钮
QPushButton * btn = new QPushButton;
//btn->show();//以顶层方式弹出窗口控件
//让btn对象依赖在mydgget窗口中
btn->setParent(this);
//显示文本
btn->setText("...");
//创建二个按钮 但是窗口只有控件大小
QPushButton * btn2 = new QPushButton("第二个",this);
//移动btn按钮
btn2->move(100,100);
//重置窗口大小
resize(600,400);
//设置固定窗口大小 不可拖动
setFixedSize(600,400);
//设置窗口标题
setWindowTitle("第一个窗口");
//创建一个自己的按钮的对象
MyPushButton * myBtn = new MyPushButton;
myBtn->setText("我自己的按钮");
myBtn->move(200,0);
myBtn->setParent(this);
}
myWidget::~myWidget()
{
qDebug()<<"myWidget的机构调用";
}
命名规范 和快捷键
- 首字母大写,单词和单词之间首字母大写
- 函数名 和变量名称 首字母小写 ,单词和单词之间首字母大写
- 运行 ctrl + r
- 编译 ctrl + b
- 整行移动 ctrl + shift + ↑ …
- 帮助文档 F1 ESC C:\Qt\Qt5.12.11\5.12.11\mingw73_64\bin\assistant.exe
- 自动对齐 ctrl + i
- 同名之间的.h 和.cpp 切换F4
创建按钮
#include "mywidget.h"
#include <QPushButton>
myWidget::myWidget(QWidget *parent)
: QWidget(parent)
{
//创建一个按钮
QPushButton * btn = new QPushButton;
//btn->show();//以顶层方式弹出窗口控件
//让btn对象依赖在mydget窗口中
btn->setParent(this);
//显示文本
btn->setText("...");
//创建二个按钮 但是窗口只有控件大小
QPushButton * btn2 = new QPushButton("第二个",this);
//移动btn按钮
btn2->move(100,100);
//重置窗口大小
resize(600,400);
//设置固定窗口大小 不可拖动
setFixedSize(600,400);
//设置窗口标题
setWindowTitle("第一个窗口");
}
myWidget::~myWidget()
{
}
对象树
在创建QObject对象时,可以提供一个其父对象,创建的这个QObject对象会自动添加到其父对象的children()列表。
在对父对象析构的时候,列表中的所有对象也同样会被析构。
这里的父对象不是继承意义上的父类。
myPushButton.cpp
#include "mypushbutton.h"
#include <QDebug>
MyPushButton::MyPushButton(QWidget *parent) : QPushButton(parent)
{
qDebug()<<"我的按钮类的构造";
}
MyPushButton::~MyPushButton()
{
qDebug()<<"我的按钮类的析构";
}
Qt中的坐标系
左上角为0。
x以右为正方向。
y以下为正方向。
信号和槽
信号槽的优点: 松散耦合:信号的发送方和接受方 本身是没有关联的。
需求:点一个按钮,可以实现关闭功能
翻译:生成一个按钮->点击->窗口(执行关闭操作)->关闭
信号的发送方 信号的接受方
信号 signal 槽 Slots
connect(信号的发送者,发送的具体信号,信号的接受者,信号的处理(槽函数))
connect(myBtn, &QPushButton::clicked, this,&QWidget::close);
connect(myBtn, &MyPushButton::clicked, this,&myWidget::close);
信号函数 需要声明 不需要实现
槽函数 需要声明 需要实现
widget.h
Teacher *zt;
Student *st;
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "teacher.h"
#include "student.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
Teacher *zt;
Student *st;
void classIsOver();
};
#endif // WIDGET_H
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
//返回值是void 需要声明 也需要实现
//可以有参数 可以发生重载
void treat();
signals:
};
#endif // STUDENT_H
Student.cpp
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::treat()
{
qDebug()<<"请老师吃饭";
}
teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//自定义信号写到这下
//返回值是void 只需要声明 不需要实现
//可以有参数 可以重载
void hungry();
};
#endif // TEACHER_H
Teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent) : QObject(parent)
{
}
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
//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 Widget::classIsOver()
{
//下课函数 调用后 触发老师饿了的信号
emit zt->hungry();
}
Widget::~Widget()
{
delete ui;
}
如果出现重载,在获取函数地址的时候会发生二义性
需要定义一个函数指针指向对应的地址。
void(Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
void(Student:: *studentSignal)(QString) = &Student::treat;
connect(zt,teacherSignal,st,studentSignal);
拓展
- 一个信号可以连接一个信号
- 一个信号可以连接多个槽
- 多个信号可以连接一个槽
- 信号和槽函数中的参数类型 必须一一对应
- 信号和槽函数中的参数个数 信号参数的个数可以多余槽参数的个数。也要保证类型一致
lambda表达式
- [] 标识符 匿名函数
- () 参数
- {} 实现体
[=]()
{
btn->setText("xiake");
}();
a
[btn]()
{
btn->setText("xiake");
btn2->setText("xiake");//btn2 看不到
}();
- = 值传递方式
- & 引用传递方式
- this 函数体内可以使用Lambda所在类中的成员变量
- a 按照值传递方式 只不过有限制
- &a a按引用传递
- = ,&a ,&b 出了a b 按照引用 其余按照值传递
- & , a,b, 除了a b按照值进行传递,其他参数都按引用进行传递
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=100+10;qDebug()<<m;});
connect(mybtn2,&QPushButton::clicked,this,[=](){qDebug()<<m;});
函数返回值:
int ret = []()->int{return 1000;}();
qDebug()<<"ret = "<<ret;
//利用lambda表达式实现点击按钮 关闭窗口
QPushButton * btn2= new QPushButton;
btn2->setText("guanbi");
btn2->move(100,100);
btn2->setParent(this);
connect(btn2,&QPushButton::clicked,this,[=](){ //this可省略
this->close();
emit zt->hungry("宫保鸡丁");
});
}