目录
1.#include<QmessageBox>
2.#include<QTime>
3.#include<qmath.h>
4.signals
4.1 先看代码结构
4.2 signals 能不能像 public 一样调用?
4.3 signals 能不能改成 private?
4.4 记住一个关键区别
5.connect用法
5.1 先看最常见的用法
5.2 connect() 的四个参数分别是什么?
5.3 写一个完整的例子
5.3.1 在头文件 widget.h 中声明槽函数
5.3.2 在源文件 widget.cpp 中实现函数
5.3.3 建立连接
5.4 连接时,为什么函数名前面有 &?
5.5 connect() 还有其他用途吗?
6.信号槽
6.1 先弄清楚信号和槽分别是什么
6.2、信号槽必须使用 signals 和 slots 声明吗?
使用 Qt 的信号和槽:
6.3 信号可以传递参数吗?
7.QByteArray
7.1 QByteArray 到底是什么?
7.2 它和 QString 有什么区别?
7.3 为什么 Qt 要设计 QByteArray?
7.4 QByteArray 常见的用法
8.QPoint
8.1 QPoint 是什么?
8.2 QPoint 有什么用?
8.2.1 记录鼠标位置
8.2.2 记录窗口或控件的位置
8.2.3 记录图形的位置
8.3 QPoint 的常见操作
8.5 QPoint 和 QPointF 有什么区别?
1.#include <QMessageBox>
这是 Qt 的消息框类,属于 Qt Widgets 模块。
它可以弹出提示框、警告框、询问框等。
例如:
QMessageBox::information(this, "提示", "操作成功!");运行后会弹出一个信息提示框。
常见用法:
函数 | 作用 |
|---|---|
| 信息提示框 |
| 警告提示框 |
| 错误提示框 |
| 询问用户 |
2.#include <QTime>
这是 Qt 中表示时间的类,可以用来获取或处理时间。
例如:
QTime time = QTime::currentTime(); qDebug() << time.toString("HH:mm:ss");可能输出:
"19:30:25"这里:
QTime:时间类。currentTime():获取当前时间。toString("HH:mm:ss"):将时间转换为时分秒格式的字符串。
注意:如果你想获取当前日期和时间,通常使用QDateTime;如果只需要计时、计算时间间隔,通常可以考虑QElapsedTimer。
3.#include <qmath.h>
这是 Qt 提供的数学相关头文件,包含一些数学函数和兼容性定义。
例如:
double x = qSqrt(25.0); double y = qPow(2.0, 3.0);结果分别是:
qSqrt(25.0):平方根,结果为5。qPow(2.0, 3.0):乘方,结果为8。
不过,对于现代 C++ 代码,通常也可以直接使用标准库:
#include <cmath> double x = std::sqrt(25.0); double y = std::pow(2.0, 3.0);4.signals
在 Qt 的QObject子类中,signals、public、private都可以出现在类的定义中,但它们的作用不同。
4.1 先看代码结构
class MyWidget : public QWidget { Q_OBJECT public: void doSomething(); signals: void mySignal(); private: int number; };这里有三个部分:
关键字 | 作用 |
|---|---|
| 公有成员,外部代码可以访问 |
| 声明信号,供 Qt 的信号槽机制使用 |
| 私有成员,通常只有类自身及友元可以访问 |
注意:signals不是用来声明普通成员函数的访问权限的,它是 Qt 提供的特殊语法。
4.2signals能不能像public一样调用?
例如:
MyWidget widget; widget.mySignal(); // 通常可以在外部代码中调用在 Qt 中,信号声明默认具有类似public的访问特性,但它的设计用途不是让你像普通函数一样随意调用,而是由对象在适当的时候发出信号。
更常见的写法是:
emit mySignal();其中:
signals:用于声明信号。emit用于发出信号。connect()用于建立信号和槽之间的连接。
例如:
signals: void mySignal(); private slots: void handleSignal() { qDebug() << "收到信号"; }建立连接:
connect(this, &MyWidget::mySignal, this, &MyWidget::handleSignal);发出信号:
emit mySignal();这样handleSignal()就会被调用。
4.3signals能不能改成private?
Qt 也支持:
private signals: void mySignal();或者:
protected signals: void mySignal();它们用于控制信号的访问权限。不过,实际使用时需要注意:访问权限主要影响谁能在 C++ 代码中调用这个信号,并不意味着私有信号就不能连接到槽函数。
4.4 记住一个关键区别
可以这样理解:
public、private:C++ 的访问控制关键字。signals:Qt 用于声明信号的特殊关键字。emit:发出信号时使用的标记,通常可以理解为一种提示;在 Qt 中它本身通常会被定义为空宏。
5.connect用法
Qt 中的connect()非常重要,它的作用是:把一个信号和一个槽函数连接起来,让信号发出时,槽函数自动执行。
可以先把它理解成:当 A 发生某件事时,自动让 B 做某件事。
5.1 先看最常见的用法
假设你正在做 Qt 音乐播放器,点击按钮后想播放音乐。
connect(ui->playButton, &QPushButton::clicked, this, &Widget::playMusic);这段代码可以拆成四个部分:
ui->playButton
发送信号的对象:播放按钮
&QPushButton::clicked
按钮被点击时发出的信号
connect()
建立信号与槽函数之间的连接
&Widget::playMusic
接收信号后执行的槽函数
当用户点击playButton时,playMusic()就会自动执行。
5.2connect()的四个参数分别是什么?
Qt 现代语法的基本形式是:
connect(发送信号的对象, 信号, 接收信号的对象, 槽函数);对应关系如下:
参数 | 含义 | 示例 |
|---|---|---|
第一个 | 谁发出信号 |
|
第二个 | 发出什么信号 |
|
第三个 | 谁接收信号 |
|
第四个 | 接收到后执行什么函数 |
|
这里的this表示当前对象。如果你在Widget的成员函数中写这段代码,this就是当前的Widget对象。
5.3 写一个完整的例子
假设你有一个Widget类。
5.3.1 在头文件widget.h中声明槽函数
class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = nullptr); private slots: void playMusic(); };这里的:
private slots: void playMusic();表示声明一个槽函数。它可以响应信号,也可以在类内部像普通成员函数一样调用。
5.3.2 在源文件widget.cpp中实现函数
void Widget::playMusic() { qDebug() << "开始播放音乐"; }5.3.3 建立连接
在构造函数中写:
connect(ui->playButton, &QPushButton::clicked, this, &Widget::playMusic);运行程序,点击按钮,就会输出:
开始播放音乐注意:以上代码假设你已经在构造函数中调用了ui->setupUi(this),并且界面上确实存在名为playButton的按钮。
5.4 连接时,为什么函数名前面有&?
例如:
&QPushButton::clicked它表示获取QPushButton类中clicked信号的成员函数指针。
再看:
&Widget::playMusic它表示获取Widget类中playMusic成员函数的指针。
这里的&不是调用函数,而是告诉connect()要连接哪个函数。
因此,下面两种写法的含义不同:
&Widget::playMusic // 获取函数指针 playMusic() // 直接调用函数5.5connect()还有其他用途吗?
有。信号不一定只能连接到你自己写的槽函数,也可以连接到 Qt 已经提供的槽函数,或者连接到一个 Lambda 表达式。
例如,点击按钮后关闭窗口:
connect(ui->closeButton, &QPushButton::clicked, this, &QWidget::close);点击closeButton后,当前窗口就会关闭。
也可以这样写:
connect(ui->playButton, &QPushButton::clicked, this, []() { qDebug() << "按钮被点击了"; });这里的[]() { ... }是 Lambda 表达式,可以理解为直接在connect()中写一个小函数,不必单独声明槽函数。
6.信号槽
6.1 先弄清楚信号和槽分别是什么
你可以把它们理解成“通知”和“处理通知的函数”。
| 信号(Signal) | 某件事情发生时发出的通知。 | 例如:按钮被点击,发出clicked信号。 |
| 槽函数(Slot) | 收到通知后执行的函数。 | 例如:pauseMusic()执行暂停音乐的操作。 |
连接之后,执行顺序是:
用户点击暂停按钮。
pauseButton发出clicked信号。Qt 根据
connect()找到对应的槽函数。pauseMusic()被调用。
注意:connect()本身不会执行pauseMusic(),它只负责建立连接。
6.2、信号槽必须使用signals和slots声明吗?
不一定。
使用 Qt 的信号和槽:
假设你想让一个自定义信号触发暂停音乐:
class Widget : public QWidget { Q_OBJECT signals: void pauseRequested(); private slots: void pauseMusic(); };其中:
signals: void pauseRequested();是声明一个信号。
private slots: void pauseMusic();是声明一个槽函数。
然后建立连接:
connect(this, &Widget::pauseRequested, this, &Widget::pauseMusic);当你发出信号:
emit pauseRequested();pauseMusic()就会执行。
这里有一个重要区别:
connect():建立连接。emit:发出信号。pauseMusic():真正执行暂停操作。
6.3 信号可以传递参数吗?
可以,而且非常常用。
例如,滑动音量条时,把音量值传给一个函数。
connect(ui->volumeSlider, &QSlider::valueChanged, this, &Widget::setVolume);假设你的槽函数是:
void Widget::setVolume(int value) { qDebug() << "当前音量:" << value; }当滑动条的值变成50时,valueChanged信号就会携带50这个参数,槽函数收到后,相当于执行:
setVolume(50);这样你就不必自己手动获取滑动条的值了。
注意,valueChanged(int)是带参数的信号,现代 Qt 写法中通常可以直接使用&QSlider::valueChanged,编译器会根据槽函数的类型匹配合适的重载。
7.QByteArray
你可以先把QByteArray理解为:Qt 中用来存储一串字节的数据类型。
它和你之前学过的QString很像,但它们的设计目的不同。我们一步一步理解。
7.1QByteArray到底是什么?
先看一个例子:
QByteArray data = "Hello";这里创建了一个QByteArray类型的变量data,里面存储着Hello这几个字符对应的字节。
可以把它想象成一排存储格
| H | e | l | l | o |
| 72 | 101 | 108 | 108 | 111 |
当然,QByteArray不只能存储文字,还可以存储图片、音频、网络数据等内容的原始字节。
7.2 它和QString有什么区别?
这是最重要的部分。
对比 |
|
|
|---|---|---|
主要用途 | 存储字节数据 | 存储文本 |
适合处理 | 网络数据、文件内容、JSON 原始数据 | 歌曲名称、用户名、界面文字 |
中文处理 | 中文通常会占多个字节,取决于编码 | 按 Unicode 文本处理 |
示例 |
|
|
例如:
QByteArray data = "Hello"; QString text = "Hello";虽然这两个变量看起来存储的内容一样,但它们的类型不同,内部表示和提供的操作也不同。
你可以简单记成:
QByteArray:关注数据的字节QString:关注数据的文本
7.3 为什么 Qt 要设计QByteArray?
假设你正在开发音乐播放器,需要从服务器获取歌曲信息。
服务器返回的数据可能是这样的 JSON:
{ "music": "晴天", "singer": "周杰伦" }Qt 中的网络请求经常会将收到的数据放在QByteArray里:
QByteArray data = reply->readAll();这里的reply通常是一个网络请求的回复对象,readAll()会读取回复中当前可读取的全部数据,并返回一个QByteArray。
接下来,你可以把这些字节数据交给 JSON 解析器:
QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(data, &error);这样就能将原始 JSON 数据解析为 Qt 可以操作的 JSON 对象。
整个过程可以理解为:
服务器返回数据(SON 格式的原始字节)QByteArray(接收和保存字节数据)解析 JSON 数据)QJsonDocument::fromJson()(
获取歌曲名称、歌手等信息
7.4QByteArray常见的用法
QByteArray data = "Hello"; // 获取字节数量 int len = data.size(); // 5 // 访问第一个字节 char ch = data[0]; // 'H' // 在末尾追加数据 data.append(" World"); // 转换成 QString QString text = QString::fromUtf8(data);注意:QString::fromUtf8()适用于数据确实采用 UTF-8 编码的情况。中文文本尤其需要注意编码问题。
另外,使用QByteArray一般需要包含头文件:
#include <QByteArray>8.QPoint
QPoint是 Qt 中表示二维坐标点的类,主要用来记录一个点的横坐标和纵坐标,也就是x和y。
你可以把它理解为:用一个变量同时保存两个整数坐标。
8.1 QPoint 是什么?
例如:
QPoint point(100, 200);这行代码创建了一个坐标点:
坐标示意图
这里:
100是横坐标x。200是纵坐标y。
可以通过成员函数获取它们:
int x = point.x(); // 100 int y = point.y(); // 2008.2 QPoint 有什么用?
在 Qt 开发中,它经常用于以下场景。
8.2.1 记录鼠标位置
例如,获取鼠标点击的位置:
QPoint pos = event->pos();pos.x()和pos.y()可以获取点击位置的坐标。注意,在 Qt 6 中具体坐标接口取决于事件类型;例如鼠标事件可以使用position().toPoint()。
8.2.2 记录窗口或控件的位置
QPoint pos(100, 200); widget->move(pos);将控件移动到指定位置。
8.2.3 记录图形的位置
绘制图形、拖动对象或处理二维坐标时,都可以使用QPoint。
8.3 QPoint 的常见操作
#include <QPoint> QPoint p(10, 20); // 获取坐标 int x = p.x(); // 10 int y = p.y(); // 20 // 修改坐标 p.setX(30); p.setY(40); // 移动坐标点 p += QPoint(5, 5); // 变成 (35, 45)这里的p += QPoint(5, 5),就是将横坐标和纵坐标分别增加 5。
8.5 QPoint 和 QPointF 有什么区别?
类型 | 坐标类型 | 示例 |
|---|---|---|
| 整数 |
|
| 浮点数 |
|
如果你需要精确表示小数坐标,例如绘图或处理鼠标的浮点位置,可以使用QPointF。