QT学习条记-QStringList,QTimer

打印 上一主题 下一主题

主题 1033|帖子 1033|积分 3099

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
QStringList-存储和管理一系列的字符串

在Qt框架中,QStringList 是一个模板类 QList<QString> 的特化,专门用于处理 QString 对象(即Qt中的字符串)的列表。当你看到这样的声明:
  1. QStringList m_rec_topicList;
复制代码
这里,m_rec_topicList 是一个 QStringList 范例的变量,用于存储和管理一系列的字符串(QString 对象)。以下是对 QStringList 在这个上下文中的具体讲解:
一、基本特性



  • 范例:QStringList 是 QList<QString> 的一个特化,因此它继承了 QList 的所有功能,并针对字符串进行了优化。
  • 存储:QStringList 内部利用动态数组来存储字符串,这意味着它可以根据需要自动调整大小。
  • 线程安全:QStringList 自己并不是线程安全的。如果在多线程情况中利用,需要采取适当的同步步伐。
二、重要功能


  • 添加和移除字符串

    • append(const QString &str):在列表末尾添加一个字符串。
    • prepend(const QString &str):在列表开头添加一个字符串。
    • insert(int i, const QString &str):在指定位置插入一个字符串。
    • removeAt(int i):移除指定位置的字符串。
    • removeOne(const QString &str):移除列表中第一次出现的指定字符串。
    • removeAll(const QString &str):移除列表中所有出现的指定字符串。

  • 访问字符串

    • at(int i) const:返回指定位置的字符串(带边界检查)。
    • operator[](int i) const:返回指定位置的字符串(不带边界检查,如果索引超出范围,结果未定义)。
    • first() const:返回列表中的第一个字符串。
    • last() const:返回列表中的最后一个字符串。
    • value(int i, const QString &defaultValue = QString()) const:返回指定位置的字符串,如果索引超出范围,则返回默认值。

  • 遍历

    • 可以利用 foreach 循环(Qt特有的语法糖)或基于范围的 for 循环(C++11及以后)来遍历 QStringList。

  • 排序

    • sort(Qt::SortOrder order = Qt::AscendingOrder):对列表进行排序,可以指定升序或降序。

  • 查找

    • indexOf(const QString &str, int from = 0) const:返回指定字符串在列表中第一次出现的索引,从指定位置开始搜索。
    • lastIndexOf(const QString &str, int from = -1) const:返回指定字符串在列表中最后一次出现的索引,从指定位置开始向后搜索(如果 from 为 -1,则从列表末尾开始搜索)。
    • contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const:检查列表中是否包罗指定字符串,可以指定是否区分大小写。

  • 毗连和分割

    • join(const QString &separator) const:将列表中的字符串毗连成一个字符串,利用指定的分隔符。
    • (留意:分割利用通常利用 QString 的 split() 方法,而不是 QStringList 的方法,由于分割的结果可以直接赋值给 QStringList。)

三、利用示例

  1. #include <QStringList>
  2. #include <QDebug>
  3. int main() {
  4. QStringList topicList;
  5. topicList.append("Qt");
  6. topicList.append("C++");
  7. topicList.prepend("Programming");
  8. qDebug() << "Topic list:" << topicList;
  9. // 排序
  10. topicList.sort();
  11. qDebug() << "Sorted topic list:" << topicList;
  12. // 查找
  13. int index = topicList.indexOf("C++");
  14. if (index != -1) {
  15. qDebug() << "C++ found at index:" << index;
  16. }
  17. // 连接
  18. QString joinedList = topicList.join(", ");
  19. qDebug() << "Joined list:" << joinedList;
  20. return 0;
  21. }
复制代码
 
在这个示例中,我们创建了一个 QStringList 变量 topicList,并向其中添加了一些字符串。然后,我们对列表进行了排序、查找和毗连利用。
QTimer-指定的时间间隔后发出信号

在C++中,特别是利用Qt框架时,QTimer 是一个常用的类,它用于在指定的时间间隔后发出信号。当你看到这样的声明:
  1. QTimer *publishTimer = nullptr;
复制代码
 
这里,publishTimer 是一个指向 QTimer 对象的指针,并且它被初始化为 nullptr,意味着它当前不指向任何有效的 QTimer 对象。以下是对这个声明的具体讲解:
一、QTimer 类



  • 功能:QTimer 类提供了定时器功能,它可以在指定的时间间隔后发出 timeout() 信号。这个信号可以被毗连到任何槽函数,以实现定时实行某些利用的目的。
  • 继承:QTimer 继承自 QObject 类,因此它拥有 QObject 的所有功能和特性,比如信号和槽机制、对象树管理等。
  • 精度:QTimer 的精度取决于底层利用系统的定时器机制,通常对于毫秒级别的定时是足够的,但对于更精确的定时(比如微秒级别),大概需要利用其他方法。
二、指针和nullptr



  • 指针:在C++中,指针是一种变量范例,它存储了另一个变量的内存地点。通过指针,你可以直接访问和利用内存中的数据。
  • nullptr:nullptr 是C++11及以后版本中引入的一个字面常量,用于表示空指针。它取代了旧的 NULL 宏(通常定义为 0 或 (void*)0),提供了更好的范例安全性和可读性。
  • 初始化:将指针初始化为 nullptr 是一种精良的编程习惯,它可以防止指针在未经初始化的情况下被利用,从而克制潜在的内存访问错误。
三、publishTimer 的利用


  • 创建 QTimer 对象
    在利用 publishTimer 之前,你需要为它分配一个有效的 QTimer 对象。这通常通过 new 关键字来完成:
  1. publishTimer = new QTimer(this); // 假设当前代码在 QObject 的子类中,且 this 指向该对象
复制代码

  • 这里,this 参数指定了 QTimer 对象的父对象。在Qt中,将对象设置为另一个对象的子对象意味着子对象的生命周期将由父对象管理。当父对象被销毁时,它的所有子对象也会被自动销毁。
  • 毗连信号和槽
    创建 QTimer 对象后,你通常需要毗连它的 timeout() 信号到一个槽函数,以便在定时器超时时实行特定的利用:
    1. connect(publishTimer, &QTimer::timeout, this, &YourClass::yourSlotFunction);
    复制代码
    这里,YourClass 是包罗槽函数的类名,yourSlotFunction 是要在定时器超时时调用的槽函数名。
  • 启动定时器
    利用 start() 方法来启动定时器,并指定时间间隔(以毫秒为单位):
    1. publishTimer->start(1000); // 每1000毫秒(即1秒)发出一次timeout信号
    复制代码
  • 制止定时器
    利用 stop() 方法来制止定时器:
    1. publishTimer->stop();
    复制代码
  • 清理
    如果你不再需要 publishTimer,并且想要释放它占用的内存,你应该先制止定时器(如果它正在运行),然后删除指针指向的对象。但是,由于 publishTimer 是父对象的子对象,在父对象被销毁时,publishTimer 也会被自动销毁。因此,在大多数情况下,你不需要手动删除它。然而,如果你将 publishTimer 设置为 nullptr(例如,在对象被销毁之前),这可以作为一种防御性编程步伐,以防止在对象生命周期的后期不测地利用该指针。
    1. publishTimer->stop();publishTimer = nullptr; // 可选,但推荐作为防御性编程步伐
    复制代码
请留意,在现代C++中(特别是利用Qt框架时),通常建议利用智能指针(如 QScopedPointer 或 QSharedPointer)来管理动态分配的对象,以克制手动管理内存和指针带来的复杂性。然而,在Qt中,由于对象树和父子关系的存在,以及 deleteLater() 方法的提供,手动管理内存的情况并不常见。
QScopedPointer /QSharedPointer-自动管理动态分配的内存,从而克制内存泄漏和悬挂指针

QScopedPointer-独占所有权-局部变量



  • 所有权:QScopedPointer 提供了严酷的独占所有权语义。这意味着一个 QScopedPointer 实例在其生命周期内拥有它所指向的对象,并且该对象不能被其他 QScopedPointer 或裸指针(raw pointer)共享。
  • 生命周期:QScopedPointer 的生命周期与其所在的作用域(scope)紧密相干。当 QScopedPointer 超出其作用域时,它所指向的对象会被自动删除。
  • 用途:QScopedPointer 通常用于局部变量,特别是当对象的生命周期应该严酷局限于某个函数或代码块时。
  • 转移所有权:虽然 QScopedPointer 不支持复制,但它可以通过 QScopedPointer<T>::take() 方法转移所有权给另一个 QScopedPointer 或裸指针,并重置自身为 nullptr。
  1. #include <QScopedPointer>
  2. #include <iostream>
  3. int main() {
  4.     // 使用 QScopedPointer 管理一个动态分配的整数数组
  5.     QScopedPointer<int[]> scopedArray(new int[10]);
  6.     // 初始化数组
  7.     for (int i = 0; i < 10; ++i) {
  8.         scopedArray[i] = i * i; // 例如,存储平方值
  9.     }
  10.     // 打印数组内容
  11.     for (int i = 0; i < 10; ++i) {
  12.         std::cout << scopedArray[i] << " ";
  13.     }
  14.     std::cout << std::endl;
  15.     // 不需要手动删除数组,QScopedPointer 会在作用域结束时自动删除它
  16.     return 0;
  17. }
复制代码
QSharedPointer-共享所有权-多个对象或线程



  • 所有权:QSharedPointer 提供了共享所有权语义。这意味着多个 QSharedPointer 实例可以共享同一个对象,并且只有当最后一个 QSharedPointer 被销毁或重置时,对象才会被删除。
  • 生命周期:QSharedPointer 的生命周期与其自身的生命周期以及它所指向的对象的共享计数有关。只要至少有一个 QSharedPointer 指向对象,对象就会保持存活。
  • 用途:QSharedPointer 通常用于需要在多个对象或线程之间共享数据的场景。
  • 线程安全:QSharedPointer 是线程安全的,可以在多个线程之间安全地共享和传递。
留意事项



  • 克制循环引用:在利用 QSharedPointer 时,要留意克制循环引用,这大概会导致内存泄漏。循环引用发生在两个或多个对象相互持有对方的 QSharedPointer 时。
  • 性能思量:虽然 QSharedPointer 提供了方便的共享所有权管理,但它也引入了额外的开销,包括维护共享计数和大概的线程同步。因此,在性能敏感的场景中,要审慎利用 QSharedPointer。
  • 裸指针的利用:尽量克制利用裸指针来管理动态内存,而是利用智能指针来确保内存的正确释放。如果必须利用裸指针,请确保在适当的时间手动删除对象,并克制悬挂指针的题目。
  1. #include <QSharedPointer>
  2. #include <iostream>
  3. class MyString {
  4. public:
  5.     MyString(const std::string &str) : data(new std::string(str)) {}
  6.     ~MyString() {
  7.         std::cout << "MyString destructor called, data: " << *data << std::endl;
  8.         delete data;
  9.     }
  10.     std::string* getData() const {
  11.         return data;
  12.     }
  13. private:
  14.     std::string *data;
  15. };
  16. int main() {
  17.     // 使用 QSharedPointer 管理一个动态分配的 MyString 对象
  18.     QSharedPointer<MyString> sharedString1(new MyString("Hello, World!"));
  19.     {
  20.         // 创建另一个 QSharedPointer,它共享同一个 MyString 对象
  21.         QSharedPointer<MyString> sharedString2 = sharedString1;
  22.         // 打印字符串内容
  23.         std::cout << *sharedString2->getData() << std::endl;
  24.         // 在这个作用域结束时,sharedString2 会被销毁,但它不会删除 MyString 对象,
  25.         // 因为还有 sharedString1 在共享它。
  26.     }
  27.     // 打印字符串内容(再次证明对象仍然存在)
  28.     std::cout << *sharedString1->getData() << std::endl;
  29.     // 当 sharedString1 被销毁时,它是最后一个共享 MyString 对象的 QSharedPointer,
  30.     // 因此 MyString 对象会被删除,并且其析构函数会被调用。
  31.     return 0;
  32. }
复制代码
QFile-创建、读取、写入和查询文件

在C++中,特别是当利用Qt框架时,QFile 类是一个用于文件利用的类。它提供了创建、读取、写入和查询文件的方法。当你看到这样的声明:
  1. QFile *logFile;
复制代码
这里,logFile 是一个指向 QFile 对象的指针。以下是对这个声明的具体讲解:
一、QFile 类



  • 功能:QFile 类提供了对文件的读写访问。它继承自 QIODevice,因此具有所有基本的输入输出功能。
  • 创建文件:你可以利用 QFile 的构造函数来创建一个指向文件的指针,但此时文件并不会被立即打开。要打开文件,你需要调用 open() 方法。
  • 读写利用:一旦文件被打开,你可以利用 read(), readLine(), write() 等方法来读取和写入文件内容。
  • 错误处理:QFile 提供了 error() 和 errorString() 方法来陈诉和处理文件利用中发生的错误。
  • 文件信息:你可以利用 size(), exists(), isReadable(), isWritable() 等方法来查询文件的属性。
二、指针的利用



  • 动态分配:通常,你会利用 new 关键字来动态分配一个 QFile 对象,并将返回的指针赋值给 logFile:
    1. logFile = new QFile("path/to/your/logfile.txt");
    复制代码
      这里,"path/to/your/logfile.txt" 是你想要利用的文件的路径。
  • 初始化:在声明 logFile 时,它并没有被初始化为指向任何有效的 QFile 对象。因此,在利用它之前,你需要确保它已经被正确地初始化和分配了内存。
  • 生命周期管理:由于 logFile 是一个指针,你需要负责它的生命周期管理。这包括在适当的时间删除它以克制内存泄漏:
    1. delete logFile;
    2. logFile = nullptr; // 可选,但推荐作为防御性编程措施
    复制代码
      然而,在Qt中,更常见的做法是利用智能指针(如 QScopedPointer 或 QSharedPointer)来自动管理内存。但请留意,QFile 通常不需要共享所有权,因此 QScopedPointer 大概是更合适的选择。然而,由于 QFile 的生命周期通常与它的利用场景紧密相干(例如,在打开和关闭文件期间),并且 QFile 对象通常不会很大,因此在实际应用中,直接利用裸指针并手动管理其生命周期也是常见的做法。
  • 利用RAII:在Qt中,更推荐的做法是利用RAII(Resource Acquisition Is Initialization)原则来管理资源。这意味着你应该在对象的构造函数中获取资源(如打开文件),并在析构函数中释放资源(如关闭文件)。这可以通过将 QFile 对象作为类的成员变量来实现,而不是利用指针。这样,当对象被销毁时,它的析构函数会自动被调用,从而释放资源。
三、示例代码

以下是一个利用 QFile 的简朴示例,演示了怎样打开文件、写入内容、关闭文件:
  1. #include <QFile>
  2. #include <QTextStream>
  3. #include <QDebug>
  4. int main() {
  5. QFile logFile("logfile.txt");
  6. if (!logFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
  7. qDebug() << "Cannot open file for writing:" << logFile.errorString();
  8. return -1;
  9. }
  10. QTextStream out(&logFile);
  11. out << "This is a log message.\n";
  12. logFile.close();
  13. return 0;
  14. }
复制代码
 
在这个例子中,logFile 是一个 QFile 对象(而不是指针),它在作用域竣事时会自动被销毁,从而关闭文件并释放相干资源。这是Qt中管理文件和其他资源的推荐方式之一。如果你确实需要利用指针(例如,由于你需要将 QFile 对象传递给多个函数或类,并且不想在每个地方都复制它),请确保你正确地管理了指针的生命周期。
QTextStream-基于文本的输入/输出功能

在Qt框架中,QTextStream 类是一个提供基于文本的输入/输出功能的类。它既可以用于读取数据(如从文件或字符串中),也可以用于写入数据(如到文件或字符串中)。当你看到这样的声明:
  1. QTextStream *logStream;
复制代码
 
这里,logStream 是一个指向 QTextStream 对象的指针。以下是对这个声明的具体讲解:
一、QTextStream 类



  • 功能:QTextStream 类提供了基于文本的输入/输出利用。它支持多种编码格式,并可以自动处理平台相干的换行符。
  • 构造函数:QTextStream 可以与多种范例的装备关联,包括 QFile、QIODevice、QString 和 QByteArray。构造函数需要传入一个指向这些装备的指针。
  • 读写利用:一旦与装备关联,你可以利用 QTextStream 的 << 和 >> 运算符来写入和读取文本数据。
  • 格式化:QTextStream 提供了多种格式化选项,如设置字段宽度、精度和对齐方式。
  • 编码:你可以指定 QTextStream 利用的编码格式,例如 UTF-8、Latin1 等。
二、指针的利用



  • 动态分配:通常,你会利用 new 关键字来动态分配一个 QTextStream 对象,并将返回的指针赋值给 logStream。但是,请留意,QTextStream 对象通常不需要动态分配,由于它们通常与特定的输入/输出装备相干联,并且这些装备的生命周期通常与 QTextStream 的利用场景紧密相干。
    1. QFile logFile("logfile.txt");
    2. if (logFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
    3. QTextStream logStream(&logFile); // 直接与 QFile 对象关联,无需动态分配
    4. logStream << "This is a log message.\n";
    5. logFile.close();
    6. }
    复制代码
  • QTextStream out(&logFile); 创建了一个 QTextStream 对象 out,并将其与已经打开的 QFile 对象 logFile 关联起来。
  • 通过 out 对象,你可以利用流利用符(如 <<)将文本数据写入到 logFile 指定的文件中。
  • 一旦 QTextStream 对象 out 与 QFile 对象 logFile 关联起来,你就可以利用 out 来输出文本了。
  • 例如,out << "This is a log message.\n"; 将字符串 "This is a log message.\n" 写入到文件中,并在末尾添加一个换行符。
  • 在这个例子中,logStream 是一个局部 QTextStream 对象,它直接与 logFile 对象关联。当 logFile 对象被销毁时(例如,当离开作用域时),它会自动关闭文件,并且与 logFile 关联的 QTextStream 对象也会自动失效。
  • 生命周期管理:如果你确实需要利用指针(例如,由于你需要将 QTextStream 对象传递给多个函数或类,并且不想在每个地方都复制它),请确保你正确地管理了指针的生命周期。但是,请留意,由于 QTextStream 通常与特定的输入/输出装备相干联,并且这些装备的生命周期通常是可以猜测的,因此直接利用局部对象而不是指针通常是更好的选择。
  • 克制内存泄漏:如果你选择利用指针,并且动态分配了 QTextStream 对象,请确保在适当的时间删除它以克制内存泄漏。然而,由于 QTextStream 通常不需要动态分配,因此这种情况很少发生。
  • 利用智能指针:虽然 QTextStream 通常不需要动态分配,但如果你确实需要这样做,并且想要自动管理内存,你可以思量利用 QScopedPointer(对于独占所有权的场景)或 QSharedPointer(对于共享所有权的场景)。但是,请留意,由于 QTextStream 的生命周期通常与它所关联的输入/输出装备的生命周期紧密相干,因此利用智能指针大概是不必要的,甚至大概导致不必要的复杂性。
三、推荐做法

在大多数情况下,建议直接利用局部 QTextStream 对象,并将它们与特定的输入/输出装备(如 QFile、QString 等)直接关联。这样做可以简化代码,并淘汰内存管理的复杂性。如果你需要将 QTextStream 对象传递给多个函数或类,并且不想在每个地方都复制它,请思量传递对输入/输出装备的引用或指针,并在需要的地方创建局部的 QTextStream 对象。
QMutex 

在Qt框架中,QMutex 是一个互斥锁(Mutex)类,它用于在多线程情况中掩护共享数据或代码段,以防止同时访问导致的竞争条件(race conditions)或数据损坏。当你看到这样的声明:
  1. QMutex logMutex;
复制代码
 
这里,logMutex 是一个 QMutex 对象,它可以用作一个同步原语来确保只有一个线程可以访问特定的资源或代码段。以下是对这个声明的具体讲解:
一、QMutex 的作用



  • 互斥性:QMutex 提供了互斥性,确保同一时间只有一个线程可以持有锁。
  • 掩护共享资源:在多线程应用中,多个线程大概会尝试同时访问和修改共享资源(如全局变量、数据结构或文件)。QMutex 可以用来掩护这些资源,防止数据竞争和不一致性。
  • 代码同步:除了掩护数据外,QMutex 还可以用于同步代码的实行顺序,确保特定的利用按预期的顺序实行。
二、QMutex 的利用



  • 锁定和解锁:要利用 QMutex,你需要在访问共享资源之前调用 lock() 方法来获取锁。在访问完成后,你应该调用 unlock() 方法来释放锁。重要的是要确保在每条实行路径上都能释放锁,以克制死锁(deadlock)的发生。
    1. QMutex logMutex;
    2. // 在线程函数或某个方法中
    3. logMutex.lock();
    4. // 访问和修改共享资源
    5. // ...
    6. logMutex.unlock();
    复制代码
  • RAII 风格的锁管理:为了克制忘记解锁或由于非常导致的解锁失败,Qt 提供了 QMutexLocker 类。这是一个基于 RAII(Resource Acquisition Is Initialization)原则的锁管理器,它在构造时自动获取锁,并在析构时自动释放锁。
    1. QMutex logMutex;
    2. // 在线程函数或某个方法中
    3. {
    4. QMutexLocker locker(&logMutex);
    5. // 访问和修改共享资源
    6. // ...
    7. // 当 locker 对象离开作用域时,它会自动调用 unlock()
    8. }
    复制代码
  • 尝试锁定:QMutex 还提供了 tryLock() 方法,它尝试获取锁但不阻塞。如果锁可用,tryLock() 将返回 true 并获取锁;如果锁不可用,它将立即返回 false 而不期待。
三、留意事项



  • 克制死锁:确保在每条实行路径上都能释放锁,特别是在利用非常处理时。
  • 性能思量:频繁地锁定和解锁大概会影响性能,特别是在高并发情况中。因此,应该尽量减小锁的作用范围,并思量利用其他同步机制(如读写锁、信号量)来优化性能。
  • 递归锁:QMutex 默认不支持递归锁定(即同一个线程不能多次获取同一个锁)。如果需要递归锁定,请利用 QRecursiveMutex。
四、应用场景



  • 日志记录:如变量名 logMutex 所暗示的,互斥锁常用于掩护日志记录利用,确保多个线程不会同时写入日志文件,从而导致日志混乱。
  • 线程间通讯:在多线程应用中,QMutex 可以与其他同步机制(如条件变量、信号槽)结合利用,以实现线程间的和谐和通讯。
  • 掩护共享数据结构:当多个线程需要访问和修改同一个数据结构时(如链表、树、哈希表等),QMutex 可以用来确保数据的一致性和完备性。
 MQTT

在Qt框架中,QMqttClient 类是用于与MQTT协议服务器进行通讯的一个客户端类。MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息传输协议,广泛应用于物联网(IoT)场景中,以实现装备之间的可靠通讯。当你看到这样的声明:
  1. QMqttClient m_client;
复制代码
这里,m_client 是一个 QMqttClient 对象,它表示一个MQTT客户端实例。以下是对这个声明的具体讲解:
一、QMqttClient 的作用



  • 毗连服务器:QMqttClient 答应你毗连到MQTT协议的消息代理(broker)服务器。
  • 发布消息:一旦毗连成功,你可以利用 QMqttClient 来发布(publish)消息到特定的主题(topic)。
  • 订阅主题:你还可以订阅(subscribe)一个或多个主题,以便吸收这些主题上的消息。
  • 处理消息:当订阅的主题上有新消息发布时,QMqttClient 会通过信号和槽机制将消息传递给应用程序进行处理。
二、QMqttClient 的利用



  • 设置服务器地点和端口:在利用 QMqttClient 之前,你需要设置MQTT服务器的地点和端口。这通常通过调用 setHostname() 和 setPort() 方法来完成。
  • 设置客户端ID:每个MQTT客户端都需要一个唯一的客户端ID来标识自己。你可以通过调用 setClientId() 方法来设置它。
  • 创建毗连:利用 connectToHost() 方法尝试毗连到MQTT服务器。毗连成功后,QMqttClient 会发出 connected 信号。
  • 发布消息:利用 publish() 方法发布消息到指定的主题。你可以指定消息的质量服务等级(QoS)和是否保留消息。
  • 订阅主题:利用 subscribe() 方法订阅一个或多个主题。当这些主题上有新消息时,QMqttClient 会发出 messageReceived() 信号。
  • 处理断开毗连:如果毗连断开,QMqttClient 会发出 disconnected 信号。你可以通过重新毗连来处理这种情况。
三、信号和槽

QMqttClient 提供了多个信号来关照应用程序关于毗连状态、消息吸收等事故。你可以利用Qt的信号和槽机制来毗连这些信号到你的槽函数中,以便处理这些事故。
四、留意事项



  • 线程安全:QMqttClient 不是线程安全的。你应该确保在一个线程中创建和利用 QMqttClient 对象,并克制在多个线程之间共享它。
  • 错误处理:在处理MQTT毗连和消息时,你应该添加适当的错误处理代码来处理大概的失败情况,如毗连失败、发布消息失败等。
  • 资源释放:在不再需要 QMqttClient 对象时,你应该确保正确释放它所占用的资源。这通常意味着调用 disconnectFromHost() 方法来断开与MQTT服务器的毗连,并删除 QMqttClient 对象。
  1. #include <QApplication>
  2. #include <QWidget>
  3. #include <QVBoxLayout>
  4. #include <QPushButton>
  5. #include <QTextEdit>
  6. #include <QMqttClient>
  7. #include <QDebug>
  8. class MqttWidget : public QWidget {
  9.     Q_OBJECT
  10. public:
  11.     MqttWidget(QWidget *parent = nullptr) : QWidget(parent), mqttClient(new QMqttClient(this)) {
  12.         QVBoxLayout *layout = new QVBoxLayout(this);
  13.         connectButton = new QPushButton("Connect to MQTT", this);
  14.         publishButton = new QPushButton("Publish Message", this);
  15.         subscribeButton = new QPushButton("Subscribe to Topic", this);
  16.         textEdit = new QTextEdit(this);
  17.         textEdit->setReadOnly(true);
  18.         layout->addWidget(connectButton);
  19.         layout->addWidget(publishButton);
  20.         layout->addWidget(subscribeButton);
  21.         layout->addWidget(textEdit);
  22.         // 设置MQTT服务器地址和端口
  23.         mqttClient->setHostname("mqtt.example.com"); // 替换为你的MQTT服务器地址
  24.         mqttClient->setPort(1883); // 替换为你的MQTT服务器端口
  25.         // 设置客户端ID
  26.         mqttClient->setClientId("myUniqueId"); // 替换为一个唯一的客户端ID
  27.         // 连接信号和槽
  28.         connect(mqttClient, &QMqttClient::connected, this, &MqttWidget::onConnected);
  29.         connect(mqttClient, QOverload<QAbstractSocket::SocketError>::of(&QMqttClient::disconnected),
  30.                 this, &MqttWidget::onDisconnected);
  31.         connect(mqttClient, &QMqttClient::messageReceived, this, &MqttWidget::onMessageReceived);
  32.         connect(connectButton, &QPushButton::clicked, this, &MqttWidget::onConnectClicked);
  33.         connect(publishButton, &QPushButton::clicked, this, &MqttWidget::onPublishClicked);
  34.         connect(subscribeButton, &QPushButton::clicked, this, &MqttWidget::onSubscribeClicked);
  35.     }
  36. private slots:
  37.     void onConnectClicked() {
  38.         mqttClient->connectToHost();
  39.     }
  40.     void onDisconnected(QAbstractSocket::SocketError error) {
  41.         qDebug() << "Disconnected from MQTT server with error:" << error;
  42.         textEdit->append("Disconnected from MQTT server.");
  43.     }
  44.     void onConnected() {
  45.         qDebug() << "Connected to MQTT server.";
  46.         textEdit->append("Connected to MQTT server.");
  47.     }
  48.     void onMessageReceived(const QByteArray &message, const QMqttTopicName &topic) {
  49.         qDebug() << "Received message on topic:" << topic.name() << "Message:" << message;
  50.         textEdit->append(QString("Received message on topic: %1\nMessage: %2").arg(topic.name()).arg(message));
  51.     }
  52.     void onPublishClicked() {
  53.         // 这里应该添加发布消息的代码,例如:
  54.         // QByteArray payload = "Hello MQTT";
  55.         // mqttClient->publish("my/topic", payload, QMqttQualityOfService::AtMostOnce);
  56.         // 但为了简化示例,这里暂时不发布消息。
  57.         qDebug() << "Publish button clicked, but no message is published in this example.";
  58.     }
  59.     void onSubscribeClicked() {
  60.         mqttClient->subscribe("my/topic");
  61.         textEdit->append("Subscribed to topic 'my/topic'.");
  62.     }
  63. private:
  64.     QMqttClient *mqttClient;
复制代码
先到这里吧,请多指教

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大号在练葵花宝典

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表