Qt学习(一、Qt简介,信号和槽)
一、 安装
。。。。。。
二、 创建第一个Qt程序
创建
-
新建,选择Qt Widgets Application
-
选择位置,选择构建套件
-
选择
类的信息
,其中 基类 有三种选择。QMainwindow
(多一个菜单栏)QWidget
(空窗口)QDialog
(对话框)
其他两个是
QWidget
的子类。有两种方式创建图形界面:代码/拖拽。
-
点击完成,会生成几个文件。源文件和头文件。还有一个 ***.pro 文件。
其中:***.pro为工程文件。
分析代码
main.cpp
:程序的入口
#include "widget.h"
// 包含一个应用程序类的头文件
#include <QApplication>
// argc 为命令行变量的数量; argv 为命令行变量的数组
int main(int argc, char *argv[])
{
// a 为应用程序对象,在Qt中,应用程序对象有且仅有一个
QApplication a(argc, argv);
// 定义一个窗口对象 w ,Widget 的父类为 QWidget
Widget w;
// 窗口对象默认不会显示,必须要调用show方法显示窗口
w.show();
// 让应用程序对象进入消息循环
return a.exec();
}
.pro 文件解释:
QT += core gui // Qt包含的模块

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets // 大于4版本以上,包含Widget模块
TARGET = MyFirstQtApp // 目标 生成的.exe程序的名称
TEMPLATE = app // 模板 应用程序得模板
SOURCES += \
main.cpp \
widget.cpp // 源文件
HEADERS += \
widget.h // 头文件
头文件:
// 防止头文件重复包含 if not define
#ifndef WIDGET_H
#define WIDGET_H
// 包含头文件 QWidget 窗口类
#include <QWidget>
// Widget 公有继承自 QWidget
class Widget : public QWidget
{
// Q_OBJECT 宏, 允许类中使用信号量和槽的机制
Q_OBJECT
public:
// 构造函数 和 析构函数
Widget(QWidget *parent = 0);
~Widget();
};
#endif // WIDGET_H
源文件:
#include "widget.h"
// 构造函数的实现,初始化列表
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
}
Widget::~Widget()
{
}
三、 创建按钮
#include "widget.h"
#include <QPushButton>
// 构造函数的实现,初始化列表
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(200,200);
// 重置窗口大小
resize(600,400);
// 设置固定的窗口大小
setFixedSize(600,400);
// 设置窗口标题
setWindowTitle("第一个窗口");
}
Widget::~Widget()
{
}
Qt中的对象树
Qt中的对象树就是Qt中对象间的父子关系,每一个对象都有它所有子对象的指针,都有一个指向其父对象的指针。当创建对象在堆区时,如果指定的父亲是QObject
派生下来的类或者是QObject
的子类派生下来的类,当父对象被析构时子对象也会被析构。在一定程度上简化了内存回收机制。
Qt中的窗口坐标系
窗口左上角为原点(0,0)。横方向为X轴,竖方向为Y轴。
四、 信号和槽
信号和槽是 Qt 特有的消息传输机制,它能将相互独立的控件关联起来。
在 Qt 中,用户和控件的每次交互过程称为一个事件,比如“用户点击按钮”是一个事件,“用户关闭窗口”也是一个事件。每个事件都会发出一个信号,例如用户点击按钮会发出“按钮被点击”的信号,用户关闭窗口会发出“窗口被关闭”的信号。
Qt 中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到“按钮被点击”的信号后,会做出“关闭自己”的响应动作;再比如输入框自己接收到“输入框被点击”的信号后,会做出“显示闪烁的光标,等待用户输入数据”的响应动作。在 Qt 中,对信号做出的响应动作就称为槽。
信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。
举例
点击第二个按钮按钮关闭窗口。
// connect(信号发送者,发送的信号[函数地址],信号接受者,处理的槽函数[函数地址]);
connect(btn2,&QPushButton::clicked,this,&Widget::close);
connect()
是 QObject
类中的一个静态成员函数,专门用来关联指定的信号函数和槽函数。
自定义的信号和槽举例
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
void OverClass();
signals:
// 自定义信号 写在singal下
// 返回值是void 只需要声明 不需要实现
// 可以有参数 可以发生重载
void hungry();
public slots:
};
#endif // TEACHER_H
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
public slots:
// 早期Qt版本,必须要写到public slots,高级版本可以写到public或者全局下
// 返回值 void 需要声明 需要实现
// 可以有参数 可以发生重载
void treat();
};
#endif // STUDENT_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* t ;
Student* s ;
};
#endif // WIDGET_H
#include "teacher.h"
Teacher::Teacher(QObject *parent) : QObject(parent)
{
}
void Teacher::OverClass()
{
emit this->hungry();
}
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::treat()
{
// 在控制台输出 需要包含头文件
qDebug() << "请老师吃饭" ;
}
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
// 创建两个对象
t = new Teacher(this);
s = new Student(this);
// 注意:下面两步是有顺序的
// 老师饿了 学生请客的 连接
connect(t,&Teacher::hungry,s,&Student::treat);
// 调用下课函数
t->OverClass();
}
Widget::~Widget()
{
}
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:
- 信号函数用
signals
关键字修饰,槽函数用public slots
、protected slots
或者private slots
修饰。signals
和slots
是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数; - 信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。
自定义的信号和槽发生重载
需要用到函数指针:
函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。
// 声明格式:类型说明符 (*函数名) (参数)
int (*fun)(int x,int y);
// 函数指针是需要把一个函数的地址赋值给它,有两种写法
fun = &Function;
fun = Function;
// 取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址
// 调用函数指针的方式也有两种:
x = (*fun)();
x = fun();
// 函数指针 指向 函数地址
void (Teacher::*teacherSignal)(QString) = &Teacher::hungry;
void (Student::*studentSlot)(QString) = &Student::treat;
connect(t,teacherSignal,s,studentSlot);
t->OverClass();
void Student::treat(QString FoodName)
{
// 去掉Qstring中的引号
// 将QString先转为QByteArray,再转为 char*
qDebug() << "请老师吃:" << FoodName.toUtf8().data();
}
信号连接信号
// 点击按钮 触发下课
QPushButton* btn = new QPushButton("下课",this);
this->resize(600,400);
connect(btn,&QPushButton::clicked,t,&Teacher::OverClass);
断开信号
可以利用disconnect
断开信号连接
// 信号断开操作 参数与connect一样
disconnect(btn,&QPushButton::clicked,t,&Teacher::OverClass);
Lambda表达式
匿名函数对象。。。先空着
其他
- 一个信号可以连接多个槽函数
- 多个信号可以连接同一个槽函数
- 信号和槽函数的参数类型必须一一对应
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)