Qt6.5类库详解:QObject

本文详细介绍了Qt库中的QObject类,涵盖其信号槽机制、对象管理、动态属性、元对象系统、事件处理、线程安全以及deleteLater函数等关键特性,并提供了使用示例和QObject对象内置定时器的概念。
摘要由CSDN通过智能技术生成

1. QObject介绍

QObject是Qt库中最重要的类之一。作为所有Qt类的基类,QObject提供了信号槽机制、对象树、动态属性、元对象系统、事件处理机制、线程安全、国际化等许多重要特性,这些特性可以帮助开发者轻松实现模块间通信、组件化、程序设计以及事件处理等方面的功能。

QObject的主要功能和特点包括:

  • 信号槽机制:允许定义信号(signal)和槽(slot)来实现对象间的通信。一个信号可以连接到多个槽函数上,也可以将多个信号连接到同一个槽函数。
  • 对象树:支持管理对象树结构的方式,允许对象包含一个父对象和零个或多个子对象。当父对象被删除时,其所有子对象也会被自动销毁。
  • 动态属性:支持添加动态属性。除了一组已经存在的静态属性之外,每个对象实例还可以动态地创建和设置新的属性,这些属性不需要在编译器层面进行定义和声明。
  • 元对象系统:为每个 QObject 和其子类提供运行时类型信息,包括对象的类名、属性、方法和信号等信息,这些信息都可以在运行时被访问或者修改。
  • 事件处理机制:支持通过发送和接收事件来实现对象间的通信。Qt 中的事件是指某种对象发生的一些动作或状态变化,通常包含一个事件类型和一些参数。QObject 可以捕获并处理各种类型的事件,也可以派发事件给其他对象进行处理。
  • 线程安全:被设计为线程安全的基础构建单元。这意味着 QObject 默认可以在多线程环境下直接使用,而无需考虑同步问题。

QObject是Qt框架的核心,提供了许多基础和关键的功能,可以帮助开发者更轻松、更高效地构建Qt应用程序。

  • 如何使用:

头文件:#include <QObject>

cmake:find_package(Qt6 REQUIRED COMPONENTS Core)

              target_link_libraries(mytarget PRIVATE Qt6::Core)

qmake:QT += core

  • QObject派生类例子:

#ifndef QOBJECTCHILDCLASS_H
#define QOBJECTCHILDCLASS_H
#include <QObject>    // 包含头文件

 // 继承于 QObject
class QObjectChildClass : public QObject
{
// 继承于 QObject 必须写的定义宏

    Q_OBJECT
public:
    // 构造函数
    explicit QObjectChildClass(QObject *parent = nullptr)
        : QObject{parent}
    {
    }

    void sendSignal(const QString& text)
    {
        // 发射一个信号
        emit sigDoSomething1(text);
    }
    
    // signals 用来修饰声明 QObjectChildClass 派生类的信号
signals:
    // 信号
    void sigDoSomething1(QString text);

     // slots 用来修改声明槽函数
private slots:
    void slotSomeFunction(int value) {}

};

#endif // QOBJECTCHILDCLASS_H

2. QObject信号

// 当对象被销毁时,发射该信号。
void destroyed(QObject * obj = nullptr)
// 当对象名称修改时,发射该信号。
void objectNameChanged(const QString &objectName, QPrivateSignal)

3. QObject基本属性

  • objectName对象名称:
// 访问函数
QString objectName() const
void setObjectName(const QString &name)
  • isWidgetType判断是否Widget对象:
// 访问函数
bool isWidgetType() const
  • isWindowType判断是否Window对象:
// 访问函数
bool isWindowType() const
  • thread对象线程

对象线程,简单理解就是信号槽函数在哪个线程上执行。

Qt 程序启动默认会创建一个主线程,用来处理主循环消息事件,所有继承于 QObject 类对象在创建时,如果没有指定线程,将默认跑在创建该对象的线程上,一般就是主线程。

// 返回对象所在的线程
QThread *QObject::thread() const
// 更改对象及其子对象的线程关联性。如果一个对象有父对象,则不能移动该对象到另一个线程中
void QObject::moveToThread(QThread *targetThread)
  • parent父对象:
// 访问函数
QObject *parent()
void setParent(QObject *parent)

QObject对象的销毁会自动销毁所有子对象。

请看下面例子代码:

#include <QObject>

// 子对象类
class QChildClass : public QObject
{
    Q_OBJECT
public:
    QChildClass(QObject* parent)
        QObject(parent)
    {}
};

// 父对象类
class QParentClass : public QObject
{
    Q_OBJECT
public:
    QParentClass(QObject* parent = nullptr)
        : QObject(parent)
    {}
};

QParentClass* pParentClass = new QParentClass();
// 创建子对象,指定父对象 pParentClass
QChildClass* pChildClass = new QChildClass(pParentClass);
// ...
delete pParentClass;    // 会自动销毁 pChildClass 子对象
//delete pChildClass;     // 在后面 delete 会导致  double free 异常
  • children子对象列表:
// 返回对象所有子对象列表
const QObjectList &children() const
  • property对象属性:

QObject的property对象属性是一个超好用的功能,可以用来保存用户自定义数据,满足各种业务逻辑需求的开发。所有QObject派生类都可以使用该对象属性。

// 访问函数
bool setProperty(const char *name, const QVariant &value)
QVariant property(const char *name) const
QList<QByteArray> dynamicPropertyNames() const

/**** 例子 ****/
QParentClass* pParentClass = new QParentClass();
// 设置属性值
pParentClass->setProperty("user_id", QVariant(100));
// ...
// 取出属性值
int i_user_id = pParentClass->property("user_id").toInt();
// ...

4. connect()连接函数

connect()连接函数用于把signal信号和slot槽函数连接到一起,当signal信号发射时,slot槽函数会响应执行。不再需要的连接需要用disconnect()断开。

注意事项:需要避免多次QObject::connect()连接,否则会有一次发射信号,多次执行槽函数的风险。

  • connect()例子:

#include <QWidget>
#include <QPushButton>

class QConnectSample : public QWidget
{
    Q_OBJECT
public:
    QConnectSample(QWidget* parent = nullptr)
        : QWidget(parent)
    {
        // 创建一个按钮
        m_pPushButton = new QPushButton("点击我", this);
        m_pPushButton->setGeometry(10, 10, 60, 32);

        // 连接按钮 clicked 点击事件
        QObject::connect(m_pPushButton, &QPushButton::clicked, this, &QConnectSample::slotPushButtonClicked);
    }
    ~QConnectSample()
    {
        QObject::disconnect(m_pPushButton, &QPushButton::clicked, this, &QConnectSample::slotPushButtonClicked);
    }

public Q_SLOTS:
    // 按钮点击处理函数
    void slotPushButtonClicked(bool checked = false)
    {
        // ...
    }

private:
    QPushButton * m_pPushButton = nullptr;
};
  • connect()连接函数第五个参数:

connect()连接函数第五个参数是Qt::ConnectionType,这个枚举描述了在信号和槽之间的连接类型。它决定一个特定信号被输送到槽函数,是立即执行,还是会放到队列排队执行。

Qt::ConnectionType五种连接类型如下:

enum ConnectionType {
    AutoConnection,            // (默认)自动根据信号发送的线程,与执行槽函数线程来选择
    DirectConnection,          // 立即执行
    QueuedConnection,          // 队列排队执行
    BlockingQueuedConnection,  // 与 Qt::QueuedConnection 相同,但会阻塞信号发送线程,直到槽函数执行返回
    UniqueConnection =  0x80   // 唯一标识;可以和以上任意连接类型组合,用按位或(|)。当设置了Qt::UniqueConnection,QObject::connect()函数如果连接已经存在(信号、槽函数和对象都相同),将返回失败。
};

5. deleteLater()延迟销毁函数

调用deleteLater()函数不会立即销毁对象,而是在下一个主消息循环才自动销毁该对象,可以减少内存泄露和double free异常风险。

/**** 例子 ****/
QPushButton *p_push_button = new QPushButton(this);
// ...
// 当不需要的时候,调用 deleteLater 自动销毁对象
p_push_button->deleteLater();

6. QObject事件处理

  • 事件接收器:

重写QObject::event()虚函数,用于接收对象事件,如果事件被处理,则返回 true

virtual bool event(QEvent *event)
  • 事件过滤器:

利用注册事件过滤器,可以捕捉处理指定对象事件。

// 注册事件过滤器
void installEventFilter(QObject *filterObj)
// 移除事件过滤器
void removeEventFilter(QObject *obj)

// 重写 QObject::eventFilter() 虚函数,用于接收注册过滤对象的事件;如果事件被处理,则返回 true
virtual bool eventFilter(QObject *watched, QEvent *event)

7. QObject对象内置定时器

Qt定时器的主要作用是定时执行特定的任务。它提供了简洁、易于使用的接口,使开发人员可以轻松创建和管理定时器对象。Qt 定时器能够提供高精度的计时能力,通常以毫秒级别为单位,以满足应用程序的需求。

  • 启动定时器函数:

/**
* @brief 启动定时器
* @param [in]int interval 定时器间隔时间,单位毫秒
* @param [in]Qt::TimerType timerType 定时器类型(精度)
*  - Qt::PreciseTimer    -> 精确的精度, 毫秒级
*  - Qt::CoarseTimer     -> 粗糙的精度, 和1毫秒的误差在5%的范围内, 默认精度
*  - Qt::VeryCoarseTimer -> 非常粗糙的精度, 精度在1秒左右
* @return 返回唯一定时器编号
**/
int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);
  • 杀死定时器函数:

/**
* @brief 杀死定时器
* @param [in]int id 定时器编号
* @return void
**/
void killTimer(int id)
  • 定时器处理函数:

// 重写 QObject::timerEvent 虚函数,用于处理定时器
virtual void timerEvent(QTimerEvent *event)
  • QObject内置定时器例子:

#include <QObject>
#include <QTimerEvent>

class QStartTimerSample : public QObject
{
    Q_OBJECT
public:
    QStartTimerSample(QObject* parent = nullptr)
        : QObject(parent)
    {
        // 启动1秒定时器;1000ms=1秒
        m_iTimerId = QObject::startTimer(1000, Qt::PreciseTimer);
    }
    ~QStartTimerSample()
    {
        // 杀死1秒定时器
        QObject::killTimer(m_iTimerId);
    }
private:
    // 定时器执行函数
    virtual void timerEvent(QTimerEvent *event)
    {
        if (event->timerId() == m_iTimerId)
        {
            // 1秒定时器ID
            // ...
        }

        QObject::timerEvent(event);
    }

private:
    int m_iTimerId = 0; // 1秒定时器ID
};

-【End】-

#想了解更多精彩内容,关注下方公众号,还有示例源码、开发工具免费下载。

喜欢本文章,记得点赞、分享、关注哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天恩软件工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值