Qt
1. Qt简介
1. qmake构建文件
文件的后缀名为.pro
QT += core gui # Qt包含模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets # 大于4版本以上 包含widget模块
CONFIG += c++17
# 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 \
widget.cpp
HEADERS += \ // 头文件
widget.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
2. Qt项目创建方法
1. Qt程序文件创建
-
创建QWidget类型的项目
-
在widget.cpp文件中添加代码
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->label->setText("你好!");
ui->pushButton->setText("关闭");
}
Widget::~Widget()
{
delete ui;
}
2. MainWindow创建
在MainWindow.cpp
在添加如下代码
#include "mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QToolBar>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// 重置窗口大小
resize(640, 480);
// 菜单栏 只能最多有一个
// 菜单栏创建
QMenuBar* bar = menuBar();
// 将菜单栏放入到窗口中
setMenuBar(bar);
// 创建菜单
QMenu* fileMenu = bar->addMenu("文件");
QMenu* editMenu = bar->addMenu("编辑");
// 创建菜单项
fileMenu->addAction("新建");
// 添加分割线
fileMenu->addSeparator();
fileMenu->addAction("打开");
// 工具栏 可以有多个
QToolBar* toolBar = new QToolBar(this);
addToolBar(Qt::LeftToolBarArea, toolBar);
// 后期设置 只允许 左右停靠
toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
// 设置浮动
toolBar->setFloatable(false);
// 设置移动 (总开关)
toolBar->setMovable(false);
// 工具栏中可以设置内容
toolBar->addAction("新建");
toolBar->addSeparator();
toolBar->addAction("打开");
//工具栏中添加控件
QPushButton* btn = new QPushButton("aa", this);
toolBar->addWidget(btn);
}
MainWindow::~MainWindow()
{
}
3. 自定义组件类
1. 自定义按钮
创建widget类型的项目
- 创建头文件
mypushbutton.h
在头文件中添加如下代码
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H
#include <QPushButton>
class MyPushButton : public QPushButton
{
Q_OBJECT
public:
explicit MyPushButton(QWidget *parent = nullptr);
~MyPushButton();
signals:
};
#endif // MYPUSHBUTTON_H
- 创建源文件
mypushbutton.cpp
在源文件中添加如下代码
#include "mypushbutton.h"
#include <QDebug>
MyPushButton::MyPushButton(QWidget *parent)
: QPushButton{parent}
{
qDebug() << "我的按钮类构造调用";
}
MyPushButton::~MyPushButton()
{
qDebug() << "我的按钮类析构调用";
}
- 在
widget.h
头文件中添加如下代码
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget> // 包含头文件 QWidget 窗口类
class Widget : public QWidget
{
Q_OBJECT // Q_OBJECT宏,允许类中使用信号和槽的机制
public:
Widget(QWidget *parent = nullptr); // 构造函数
~Widget(); // 析构函数
};
#endif // WIDGET_H
- 在
widget.cpp
源文件中添加如下代码
#include "widget.h"
#include <QPushButton> // 按钮控件的头文件
#include "mypushbutton.h"
#include <QDebug>
// 命名规范
// 类名 首字母大写,单词和单词之间首字母大写
// 函数名 变量名称 首字母小写,单词和单词之间首字母大写
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
// 创建一个按钮
QPushButton* btn = new QPushButton;
// btn->show(); // show以顶层方式弹出窗口控件
// 让btn对象 依赖Widget窗口中
btn->setParent(this);
// 显示文本
btn->setText("第一个按钮");
// 创建第二个按钮 按照控件的大小创建窗口
QPushButton* btn2 = new QPushButton("第二个按钮", this);
// 移动btn2按钮
btn2->move(100, 100);
// 按钮重新设定大小
btn2->resize(100, 100);
// 重置窗口的大小
resize(600, 400);
// 设置固定窗口大小
setFixedSize(600, 400);
// 设置窗口的标题
setWindowTitle("窗口");
// 创建一个自己的按钮对象
MyPushButton* myBtn = new MyPushButton;
myBtn->setText("我自己的按钮");
myBtn->move(200, 0);
myBtn->setParent(this); // 设置到对象树中
// 点击我的按钮 关闭窗口
// 参数1 信号的发送者 参数2 发送的信号<信号的地址>(函数的地址) 参数3 信号的接受者 参数4 处理的槽函数
connect(myBtn, &MyPushButton::clicked, this, &Widget::close);
// connect(myBtn, &QPushButton::clicked, this, &QWidget::close);
}
Widget::~Widget()
{
qDebug() << "Widget的析构调用";
}
- 在
main.cpp
文件中添加如下代码
#include "widget.h"
#include <QApplication> // 包含一个应用程序类的头文件
// main程序的入口 argc命令行变量的数量 argv命令行变量的数组
int main(int argc, char *argv[])
{
// a应用程序对象,在Qt中,应用程序对象 有且仅有一个
QApplication a(argc, argv);
// 窗口对象 Widget父类 -> QWidget
Widget w;
// 窗口对象 默认不会显示,必须要调用show方法显示窗口
w.show();
// 让应用程序对象进入消息循环
// 让代码阻塞到这行
return a.exec();
}
2. 创建自定义类
创建widget类型的项目
- 创建
Teacher类
老师类 的头文件teacher.h
和源文件teacher.cpp
在头文件teacher.h
中添加如下代码
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
// 自定义信号 写到signal下
// 返回值void,只需要声明,不需要实现
// 可以有参数 (可以重载)
void hungry();
void hungry(QString foodName);
};
#endif // TEACHER_H
在源文件teacher.cpp
中添加如下代码
#include "teacher.h"
Teacher::Teacher(QObject *parent)
: QObject{parent}
{
}
- 创建
Student类
学生类 的头文件student.h
和源文件student.cpp
在头文件student.h
中添加如下代码
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
// 槽函数 高版本写在public或全局下
// 返回值void,需要声明,也需要实现
// 可以有参数(可以重载)
void treat();
void treat(QString foodName);
signals:
};
#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)
{
//QString -> char * 先转成 QByteArray ( .toUtf8() ) 再转 char * ( .data() )
qDebug() << "请老师吃饭,老师要吃" << foodName.toUtf8().data();
}
- 修改widget文件
在头文件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 = nullptr);
~Widget();
Teacher* zt;
Student* st;
void classIsOver();
};
#endif // WIDGET_H
在源文件widget.cpp
中添加如下代码
#include "widget.h"
#include <QPushButton>
// Teacher类 老师类
// Student类 学生类
// 下课后 老师会触发一个信号 -> 饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
// 创建一个老师对象
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);
// 拓展
// 1.信号是可以连接信号
// 2.一个信号可以连接多个槽函数
// 3.多个信号可以连接同一个槽函数
// 4.信号和槽函数的参数 必须类型一一对应
// 5.信号和槽的参数个数 是不是要一致? 信号的参数个数 可以多余槽函数的参数个数
// Qt4版本以前的信号和槽函数连接方式
// 利用Qt4信号槽 连接无参版本
// Qt4版本 底层SIGNAL("hungry") SLOT("treat")
connect(zt, SIGNAL(hungry()), st, SLOT(treat()));
// Qt4版本优点:参数直观 缺点:类型不做检测
// 利用lambda表达式 实现点击按钮 关闭窗口
QPushButton* btn2 = new QPushButton;
btn2->setText("关闭");
btn2->move(100, 0);
btn2->setParent(this);
connect(btn2, &QPushButton::clicked, this, [=](){
this->close();
emit zt->hungry("宫保鸡丁");
});
// lambda表达式 最常用 [=](){}
}
void Widget::classIsOver()
{
// 下课函数,调用后 触发老师饿了的信号
//emit zt->hungry();
emit zt->hungry("宫保鸡丁");
}
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();
}