QObject::disconnect概述

目录

​编辑

1.概要

2.内容

作用

语法

参数说明

常见用法示例

1. 断开特定信号与槽

2. 断开发送者的所有信号

3. 断开接收者的所有槽

4. 断开特定信号与特定槽

注意事项

典型问题场景

3.关联链接

4.关联知识

1.qt 断开一个信号的全部绑定

核心方法

关键点说明

完整示例

Qt4 语法(使用 SIGNAL/SLOT 宏):

Qt5+ 语法(类型安全,推荐):

注意事项

扩展场景

2.发送完这个信号,就删除这个信号的全部链接,是否有问题 

核心问题分析

1. 信号发射的同步性

2. 在槽函数中断开连接

解决方案

方案 1:延迟断开(推荐)

方案 2:标记位控制

方案 3:单次连接(Qt5+)

注意事项

总结

3.绑定一次只执行一次,下次还想执行,再重新绑定 

方案 1:使用 Qt::UniqueConnection(推荐)

方案 2:手动断开所有连接

注意事项

扩展场景

总结

4.Qt::UniqueConnection 

核心行为

代码示例

典型应用场景

与其他连接类型的对比

注意事项

调试技巧

5.绑定一次只执行一次,下次还想执行,再重新绑定、举例 

方案 1:使用 Qt::UniqueConnection + 手动断开所有连接

方案 2:纯 Qt::UniqueConnection(无需手动断开)

选择方案的依据

关键注意事项

6.QObject::disconnect有几种重载 

1. 断开特定连接(精确匹配)

2. 断开所有接收者的槽(针对信号)

3. 断开接收者的所有槽(针对对象)

4. 使用 QMetaMethod 的重载

5. 断开特定连接(通过连接指针)

6. 支持函数指针/Lambda 的重载(Qt5+)

总结

7.重载代码解析

1. 基础信号槽断开(精确匹配)

2. 元对象方法断开(动态匹配)

3. 实例方法简化调用(默认发送者)

4. 断开接收者的所有槽

5. 通过连接指针断开

总结:重载形式与用途

8.函数解析

函数签名

核心功能

参数组合逻辑

使用场景示例

注意事项


1.概要

2.内容

QObject::disconnect 是 Qt 框架中用于断开信号与槽连接的方法。以下是其核心概念和使用说明:


作用

  • 断开信号与槽的关联,停止信号触发时自动调用对应的槽函数。
  • 可用于动态管理对象间的通信关系,避免内存泄漏或无效调用。

语法

bool QObject::disconnect(
    const QObject *sender, 
    const char *signal, 
    const QObject *receiver, 
    const char *method
)

或简化形式:

bool QObject::disconnect(const QMetaObject::Connection &connection);


参数说明

  1. sender:发送信号的对象指针(若为 nullptr,则匹配所有发送者)。
  2. signal:要断开的信号签名(如 "clicked()"),若为 nullptr 则断开所有信号。
  3. receiver:接收信号的对象指针(若为 nullptr,则匹配所有接收者)。
  4. method:要断开的槽函数签名,若为 nullptr 则断开所有槽。

常见用法示例

1. 断开特定信号与槽

// 连接时保存返回的 QMetaObject::Connection 对象
QMetaObject::Connection conn = connect(button, &QPushButton::clicked, this, &MyClass::handleClicked);


// 断开连接
disconnect(conn);
2. 断开发送者的所有信号
disconnect(button, nullptr, nullptr, nullptr); // 断开 button 的所有信号
3. 断开接收者的所有槽
disconnect(nullptr, nullptr, this, nullptr); // 断开 this 对象的所有槽
4. 断开特定信号与特定槽
disconnect(button, SIGNAL(clicked()), this, SLOT(handleClicked()));

注意事项

  1. 参数匹配:需确保 signal 和 method 的签名(参数类型和顺序)与连接时完全一致。
  2. 上下文对象:若连接时使用了 Qt::QueuedConnection,需确保接收对象存活。
  3. Lambda 表达式:若槽是 Lambda,需保存 QMetaObject::Connection 对象才能断开。
  4. 返回值:返回 true 表示断开成功,false 表示未找到匹配连接。

典型问题场景

  • 断开失败:检查信号/槽签名是否完全匹配(包括参数类型)。
  • 野指针:对象被删除后未正确管理连接,可能导致崩溃。
  • 多线程:跨线程断开连接需确保线程安全。

通过合理使用 disconnect,可以灵活控制 Qt 对象间的交互逻辑。

3.关联链接

4.关联知识

1.qt 断开一个信号的全部绑定

在 Qt 中,若需断开某个信号的所有绑定(即所有连接到该信号的槽函数),可通过以下方式实现:


核心方法

使用 QObject::disconnect() 的重载形式,将 接收者 (receiver) 和 槽函数 (method) 参数设为 nullptr

// 断开发送者 sender 的 signalSignal 信号的所有连接
disconnect(sender, SIGNAL(signalSignal()), nullptr, nullptr);


// 或(Qt5+ 推荐使用函数指针语法)
disconnect(sender, &SenderClass::signalSignal, nullptr, nullptr);

关键点说明

  1. 参数匹配
    • sender:信号的发送者对象。
    • signal:需断开的信号(如 SIGNAL(clicked()) 或 &QPushButton::clicked)。
    • receiver 和 method 设为 nullptr,表示断开该信号与所有接收者所有槽函数的关联。
  2. 返回值
    • 返回 true 表示至少有一个连接被断开,false 表示无匹配连接。

完整示例

假设有一个按钮 button,需断开其 clicked() 信号的所有绑定:

Qt4 语法(使用 SIGNAL/SLOT 宏):
disconnect(button, SIGNAL(clicked()), nullptr, nullptr);
Qt5+ 语法(类型安全,推荐):
disconnect(button, &QPushButton::clicked, nullptr, nullptr);

注意事项

  1. 线程安全:若信号涉及跨线程连接(如 Qt::QueuedConnection),需确保操作在正确的线程执行。
  2. Lambda 表达式:若槽是 Lambda,需保存连接返回的 QMetaObject::Connection 对象才能断开。
  3. 对象生命周期:确保发送者 (sender) 未被销毁,否则可能引发野指针问题。

扩展场景

  • 断开所有信号:若需断开某个对象的所有信号,可遍历其元对象信息,但 Qt 未直接提供 API,需手动实现。
  • 调试连接:使用 qDebug() << sender->metaObject()->className() << "connections:" << sender->metaObject()->methodCount(); 查看对象连接状态。

通过灵活使用 disconnect,可有效管理 Qt 对象间的动态通信关系。

2.发送完这个信号,就删除这个信号的全部链接,是否有问题 

在 Qt 中,若希望在发送完信号后自动断开该信号的所有连接,需根据具体场景谨慎处理,否则可能导致以下问题:


核心问题分析

1. 信号发射的同步性
  • Qt 信号的槽函数默认在同一线程同步执行。当信号被触发时,所有连接的槽函数会立即执行完毕,之后控制权才会返回给发射信号的代码。
  • 若直接在信号发射后调用 disconnect:此时所有槽函数已执行完毕,断开连接是安全的,但无法阻止本次信号触发的槽函数执行
2. 在槽函数中断开连接
  • 若在某个槽函数内部调用 disconnect,则:
    • 该槽函数之后的槽函数将不再执行(因为连接已被断开)。
    • 可能导致逻辑错误,尤其是当多个槽函数依赖该信号时。

解决方案

方案 1:延迟断开(推荐)

使用 Qt::QueuedConnection 将断开操作推迟到事件循环的下一轮,确保所有槽函数执行完毕:

// 在信号发射后,通过队列连接延迟断开
QMetaObject::invokeMethod(this, [this]() {
    disconnect(sender, &SenderClass::signalSignal, nullptr, nullptr);
}, Qt::QueuedConnection);
方案 2:标记位控制

通过标志位控制是否允许信号触发:

bool m_allowSignal = true;

// 发射信号前设置标志位
void SenderClass::emitSignal() {
    if (m_allowSignal) {
        m_allowSignal = false;
        emit signalSignal();
        // 信号发射后断开连接(可选)
        disconnect(this, &SenderClass::signalSignal, nullptr, nullptr);
    }
}
方案 3:单次连接(Qt5+)

使用 Qt::UniqueConnection 确保信号仅触发一次:

connect(sender, &SenderClass::signalSignal, receiver, &ReceiverClass::slot, Qt::UniqueConnection);

注意事项

  1. 对象生命周期
    • 确保发送者 (sender) 和接收者 (receiver) 在断开连接后不会被立即销毁,避免野指针。
  2. 多线程场景
    • 若信号跨线程,需通过 QMetaObject::invokeMethod 确保操作在正确的线程执行。
  3. Lambda 表达式
    • 若槽是 Lambda,需保存 QMetaObject::Connection 才能断开。

总结

  • 直接断开所有连接:在信号发射后调用 disconnect 是安全的,但无法阻止本次信号触发的槽函数。
  • 需阻止本次触发:需结合标志位或单次连接 (Qt::UniqueConnection)。
  • 最佳实践:优先使用 Qt::QueuedConnection 延迟断开,或设计逻辑避免在信号发射后动态修改连接。

3.绑定一次只执行一次,下次还想执行,再重新绑定 

在 Qt 中实现「发送信号后自动断开所有连接,确保每次绑定仅执行一次」的需求,可通过以下两种方案实现:


方案 1:使用 Qt::UniqueConnection(推荐)

Qt 内置的 单次连接 机制,自动在槽函数执行后断开连接,无需手动管理:

void ReceiverClass::requestExecution() {
    // 每次执行前重新绑定
    connect(sender, &SenderClass::signalSignal, 
            this, &ReceiverClass::slot, 
            Qt::UniqueConnection);
    // 触发信号
    emit sender->signalSignal();
}

特点

  • 每个连接仅触发一次,自动断开。
  • 无需手动调用 disconnect
  • 适合「绑定一次,执行一次」的场景。

方案 2:手动断开所有连接

若需在信号发射后立即断开所有连接(即使槽函数未执行完),需结合 QMetaObject::invokeMethod 延迟操作:

// 发射信号后,延迟断开所有连接
void SenderClass::emitSignal() {
    emit signalSignal();
    
    // 通过队列连接确保断开操作在槽函数执行后执行
    QMetaObject::invokeMethod(this, [this]() {
        disconnect(this, &SenderClass::signalSignal, nullptr, nullptr);
    }, Qt::QueuedConnection);
}

特点

  • 所有槽函数执行完毕后断开连接。
  • 后续信号不会触发已断开的槽。
  • 需确保发送者 (this) 在断开前未被销毁。

注意事项

  1. 线程安全
    • 若信号跨线程,使用 Qt::QueuedConnection 确保操作在正确的线程执行。
  2. 对象生命周期
    • 避免在断开连接后访问已销毁的对象。
  3. Lambda 表达式
    • 若槽是 Lambda,需保存 QMetaObject::Connection 才能断开。
  4. 性能影响
    • 频繁连接/断开可能影响性能,建议复用连接或优化逻辑。

扩展场景

  • 动态绑定需求:若需多次执行,每次执行前重新绑定:

    void ReceiverClass::requestExecution() {
        // 每次执行前重新绑定
        connect(sender, &SenderClass::signalSignal, 
                this, &ReceiverClass::slot, 
                Qt::UniqueConnection);
        // 触发信号
        emit sender->signalSignal();
    }
  • 调试连接状态

    qDebug() << "Active connections:" 
             << sender->metaObject()->className() 
             << sender->receivers(SIGNAL(signalSignal()));

总结

  • 优先使用 Qt::UniqueConnection:简洁高效,适合单次触发场景。
  • 手动断开需谨慎:确保逻辑正确性和线程安全,避免野指针。
  • 根据需求选择方案:若需严格「每次绑定仅执行一次」,方案 1 更优;若需全局控制信号生命周期,方案 2 更灵活。

4.Qt::UniqueConnection 

Qt::UniqueConnection 是 Qt 框架中用于信号与槽连接的一种特殊标志,其核心作用是确保某个信号与槽的组合仅连接一次。若重复尝试连接,Qt 会自动忽略后续请求,避免槽函数被多次调用。


核心行为

  1. 唯一性保证
    • 当使用 Qt::UniqueConnection 连接信号与槽时,Qt 会检查该信号和槽是否已存在相同的连接。
    • 如果存在,则不会创建新连接connect() 函数返回 false
    • 如果不存在,则创建新连接,connect() 返回 true
  2. 自动去重
    • 适用于需要确保「信号触发时,槽函数仅执行一次」的场景,无需手动管理连接状态。

代码示例

// 对象声明
QObject *sender = new QObject;
QObject *receiver = new QObject;

// 使用 Qt::UniqueConnection 连接信号与槽
bool isConnected = connect(
    sender, &SenderClass::mySignal,
    receiver, &ReceiverClass::mySlot,
    Qt::UniqueConnection
);

// 尝试重复连接(不会生效)
bool isDuplicate = connect(
    sender, &SenderClass::mySignal,
    receiver, &ReceiverClass::mySlot,
    Qt::UniqueConnection
);

qDebug() << "First connection:" << isConnected;    // 输出 true
qDebug() << "Duplicate connection:" << isDuplicate; // 输出 false

典型应用场景

  1. 单次初始化操作
    • 例如,在对象初始化时连接信号,确保后续不会重复绑定。
  2. 资源敏感操作
    • 避免因重复连接导致槽函数多次执行,引发性能问题或状态不一致。
  3. 动态绑定控制
    • 在复杂逻辑中,确保某个信号与槽的组合在特定条件下仅连接一次。

与其他连接类型的对比

连接类型行为
Qt::AutoConnection默认类型,允许重复连接(槽函数可能被多次调用)。
Qt::QueuedConnection跨线程时通过事件队列传递信号,允许重复连接。
Qt::UniqueConnection确保信号与槽的组合唯一,重复连接无效。

注意事项

  1. 连接失败处理
    • 通过检查 connect() 的返回值判断是否连接成功。
  2. 动态对象生命周期
    • 确保发送者 (sender) 和接收者 (receiver) 在连接期间有效,避免野指针。
  3. Lambda 表达式
    • 若槽是 Lambda,需保存 QMetaObject::Connection 对象才能手动断开。

调试技巧

  • 查询现有连接

    int connectionCount = sender->metaObject()->method(
        sender->metaObject()->indexOfSignal("mySignal()")
    ).connectionCount();
    qDebug() << "Active connections for mySignal:" << connectionCount;
  • 检查接收者

    QList<QObject*> receivers = sender->receivers(SIGNAL(mySignal()));
    qDebug() << "Receivers for mySignal:" << receivers;


通过合理使用 Qt::UniqueConnection,可以简化信号与槽的管理逻辑,避免因重复连接导致的意外行为,提升代码的健壮性。

5.绑定一次只执行一次,下次还想执行,再重新绑定、举例 

在 Qt 中实现「发送信号后自动删除所有连接,确保每次绑定仅执行一次」的需求,可以通过以下两种方案实现。这里以具体代码示例说明:


方案 1:使用 Qt::UniqueConnection + 手动断开所有连接

#include <QObject>
#include <QDebug>

class Sender : public QObject {
    Q_OBJECT
public:
    void trigger() {
        emit mySignal();
        // 使用队列连接确保断开操作在槽函数执行后执行
        QMetaObject::invokeMethod(this, [this]() {
            disconnect(this, &Sender::mySignal, nullptr, nullptr);
        }, Qt::QueuedConnection);
    }

signals:
    void mySignal();
};

class Receiver : public QObject {
    Q_OBJECT
public slots:
    void handleSignal() {
        qDebug() << "Slot executed";
    }
};

// 使用示例
int main() {
    Sender sender;
    Receiver receiver;

    // 第一次绑定并触发
    QObject::connect(&sender, &Sender::mySignal, &receiver, &Receiver::handleSignal);
    sender.trigger();  // 输出 "Slot executed"

    // 第二次触发(无连接,无输出)
    sender.trigger();  // 无输出

    // 重新绑定并触发
    QObject::connect(&sender, &Sender::mySignal, &receiver, &Receiver::handleSignal);
    sender.trigger();  // 输出 "Slot executed"

    return 0;
}

行为解释

  1. trigger() 方法
    • 发射信号 mySignal
    • 通过 QMetaObject::invokeMethod 延迟断开所有连接,确保槽函数执行完毕后再断开。
  2. 第一次触发
    • 绑定连接并执行槽函数。
    • 断开所有连接,后续触发无响应。
  3. 重新绑定
    • 再次绑定后触发,槽函数重新执行。

方案 2:纯 Qt::UniqueConnection(无需手动断开)

#include <QObject>
#include <QDebug>

class Sender : public QObject {
    Q_OBJECT
public:
    void trigger() {
        emit mySignal();
    }

signals:
    void mySignal();
};

class Receiver : public QObject {
    Q_OBJECT
public slots:
    void handleSignal() {
        qDebug() << "Slot executed";
    }
};

// 使用示例
int main() {
    Sender sender;
    Receiver receiver;

    // 使用 Qt::UniqueConnection 连接
    QObject::connect(&sender, &Sender::mySignal,
                     &receiver, &Receiver::handleSignal,
                     Qt::UniqueConnection);

    // 第一次触发(执行)
    sender.trigger();  // 输出 "Slot executed"

    // 第二次触发(不执行,因连接已唯一)
    sender.trigger();  // 无输出

    // 重新绑定并触发
    QObject::connect(&sender, &Sender::mySignal,
                     &receiver, &Receiver::handleSignal,
                     Qt::UniqueConnection);
    sender.trigger();  // 输出 "Slot executed"

    return 0;
}

行为解释

  1. Qt::UniqueConnection
    • 确保信号与槽的组合唯一,重复连接无效。
  2. 第一次触发
    • 槽函数执行一次,连接自动失效。
  3. 重新绑定
    • 再次连接后触发,槽函数重新执行。

选择方案的依据

方案适用场景
方案 1需全局控制信号生命周期,确保所有连接在信号发射后断开。
方案 2需确保单个连接仅执行一次,无需全局断开。

关键注意事项

  1. 线程安全
    • 若信号跨线程,使用 Qt::QueuedConnection 确保操作在正确的线程执行。
  2. 对象生命周期
    • 避免在断开连接后访问已销毁的对象。
  3. Lambda 表达式
    • 若槽是 Lambda,需保存 QMetaObject::Connection 才能断开。
  4. 性能影响
    • 频繁连接/断开可能影响性能,建议复用连接或优化逻辑。

根据需求选择合适方案,若需严格「每次绑定仅执行一次且全局断开」,方案 1 更合适;若仅需单次触发,方案 2 更简洁。

6.QObject::disconnect有几种重载 

QObject::disconnect 在 Qt 中有多种重载形式,主要用于灵活断开信号与槽的连接。以下是常见的重载类型及用途:

1. 断开特定连接(精确匹配)

static bool disconnect(
    const QObject *sender, 
    const char *signal, 
    const QObject *receiver, 
    const char *method
);
  • 作用:断开 sender 对象的 signal 信号到 receiver 对象的 method 槽的特定连接。
  • 参数:需明确指定发送者、信号、接收者及槽函数。

2. 断开所有接收者的槽(针对信号)

static bool disconnect(
    const QObject *sender, 
    const char *signal
);
  • 作用:断开 sender 对象的 signal 信号到所有接收者的槽的连接。
  • 适用场景:清理某个信号的所有连接。

3. 断开接收者的所有槽(针对对象)

static bool disconnect(
    const QObject *receiver, 
    const char *method
);
  • 作用:断开 receiver 对象的 method 槽到所有发送者信号的连接。
  • 适用场景:清理某个对象的特定槽的所有连接。

4. 使用 QMetaMethod 的重载

static bool disconnect(
    const QObject *sender, 
    const QMetaMethod &signal, 
    const QObject *receiver, 
    const QMetaMethod &method
);
  • 作用:通过元对象方法(QMetaMethod)断开连接,支持动态或运行时确定的信号与槽。
  • 适用场景:需通过元对象系统动态处理连接时。

5. 断开特定连接(通过连接指针)

static bool disconnect(QMetaObject::Connection connection);

  • 作用:通过 QObject::connect() 返回的 QMetaObject::Connection 断开特定连接。
  • 优势:精准控制单个连接,避免误断其他连接。

6. 支持函数指针/Lambda 的重载(Qt5+)

static bool disconnect(
    const QObject *sender, 
    PointerToMemberFunction signal, 
    const QObject *receiver, 
    Functor method
);
  • 作用:支持断开使用函数指针、Lambda 或 Functor 连接的槽。
  • 适用场景:现代 Qt 语法(如 connect 的新语法)生成的连接。

总结

QObject::disconnect 共有 6 种核心重载,覆盖以下场景:

  • 精确断开(发送者+信号+接收者+槽)。
  • 按信号断开所有接收者
  • 按槽断开所有发送者
  • 通过连接指针断开
  • 支持元对象方法(QMetaMethod
  • 支持函数指针/Lambda/Functor(Qt5+)。

这些重载提供了灵活的断开机制,可根据需求选择最合适的参数组合。

7.重载代码解析

static bool disconnect(const QObject *sender, const char *signal,
                           const QObject *receiver, const char *member);
    static bool disconnect(const QObject *sender, const QMetaMethod &signal,
                           const QObject *receiver, const QMetaMethod &member);
    inline bool disconnect(const char *signal = nullptr,
                           const QObject *receiver = nullptr, const char *member = nullptr) const
        { return disconnect(this, signal, receiver, member); }
    inline bool disconnect(const QObject *receiver, const char *member = nullptr) const
        { return disconnect(this, nullptr, receiver, member); }
    static bool disconnect(const QMetaObject::Connection &);

QObject::disconnect 的重载形式根据参数和功能的不同,可以分为以下类别。以下是您提供的代码片段的详细解析和归类:


1. 基础信号槽断开(精确匹配)

static bool disconnect(
    const QObject *sender, 
    const char *signal, 
    const QObject *receiver, 
    const char *member
);
  • 参数:发送者对象、信号名称(字符串)、接收者对象、槽函数名称(字符串)。
  • 功能:断开 sender 的 signal 信号到 receiver 的 member 槽的特定连接。
  • 使用场景:明确知道发送者、信号、接收者及槽函数时,精准断开连接。

2. 元对象方法断开(动态匹配)

static bool disconnect(
    const QObject *sender, 
    const QMetaMethod &signal, 
    const QObject *receiver, 
    const QMetaMethod &member
);
  • 参数:发送者对象、QMetaMethod 类型的信号、接收者对象、QMetaMethod 类型的槽。
  • 功能:通过元对象系统动态断开连接,支持运行时解析信号和槽。
  • 使用场景:需要动态处理连接(如反射或跨线程场景)。

3. 实例方法简化调用(默认发送者)

inline bool disconnect(
    const char *signal = nullptr, 
    const QObject *receiver = nullptr, 
    const char *member = nullptr
) const { 
    return disconnect(this, signal, receiver, member); 
}
  • 参数:信号名称、接收者对象、槽函数名称(均可选)。
  • 功能:将当前对象(this)作为发送者,简化调用。
  • 使用场景:在对象内部断开自身发出的信号,无需显式指定 sender

4. 断开接收者的所有槽

inline bool disconnect(
    const QObject *receiver, 
    const char *member = nullptr
) const { 
    return disconnect(this, nullptr, receiver, member); 
}
  • 参数:接收者对象、槽函数名称(可选)。
  • 功能:断开当前对象(this)的所有信号到 receiver 的 member 槽的连接。
  • 使用场景:清理某个接收者的特定槽或所有槽(member 为 nullptr 时)。

5. 通过连接指针断开

static bool disconnect(const QMetaObject::Connection &);
  • 参数QMetaObject::Connection 类型的引用(由 connect() 返回)。
  • 功能:通过连接指针精准断开单个连接。
  • 使用场景:需要管理特定连接的生命周期(如临时连接)。

总结:重载形式与用途

重载形式参数类型核心功能
精确匹配字符串信号/槽断开特定发送者、信号、接收者、槽的连接。
元对象动态匹配QMetaMethod支持运行时动态解析信号和槽。
实例简化调用默认发送者为 this在对象内部断开自身信号,无需显式指定发送者。
接收者清理接收者 + 可选槽断开当前对象到某个接收者的所有槽或特定槽。
连接指针断开QMetaObject::Connection通过连接指针精准控制单个连接的断开。

这些重载提供了从精细控制到批量清理的多种操作方式,可根据具体需求选择最合适的断开策略。

8.函数解析

inline bool disconnect(
    const char *signal = nullptr, 
    const QObject *receiver = nullptr, 
    const char *member = nullptr
) const { 
    return disconnect(this, signal, receiver, member); 
} 详细讲讲

这个 disconnect 的重载函数是 QObject 的一个成员函数,设计目的是让对象能够直接断开自身发出的信号,而无需显式传递 this 作为发送者。以下是其详细解析:


函数签名

inline bool disconnect(
    const char *signal = nullptr, 
    const QObject *receiver = nullptr, 
    const char *member = nullptr
) const { 
    return disconnect(this, signal, receiver, member); 
}
  • inline:函数在编译时内联展开,避免函数调用开销。
  • const:函数不会修改对象状态(但会修改连接关系,Qt 内部处理此细节)。
  • 参数默认值:所有参数均可省略,提供灵活的调用方式。

核心功能

通过调用静态 disconnect 函数,将当前对象(this)作为信号发送者,断开其信号与接收者的槽的连接。支持以下操作:

  1. 断开所有连接
    disconnect(); // 等效于 disconnect(this, nullptr, nullptr, nullptr)
    • 断开当前对象所有信号所有接收者所有槽的连接。
  2. 断开特定信号的所有连接
    disconnect("mySignal"); // 等效于 disconnect(this, "mySignal", nullptr, nullptr)
    • 断开当前对象的 mySignal 信号到所有接收者所有槽
  3. 断开特定信号到特定接收者的所有槽
    disconnect("mySignal", receiverObj); // 等效于 disconnect(this, "mySignal", receiverObj, nullptr)
    • 断开当前对象的 mySignal 信号到 receiverObj 的所有槽
  4. 断开特定信号到特定槽
    disconnect("mySignal", receiverObj, "onMySignal");
    • 断开当前对象的 mySignal 信号到 receiverObj 的 onMySignal 槽的单一连接
  5. 断开特定接收者的所有槽
    disconnect(nullptr, receiverObj); // 等效于 disconnect(this, nullptr, receiverObj, nullptr)
    • 断开当前对象所有信号到 receiverObj 的所有槽

参数组合逻辑

参数组合行为
signal = nullptr断开所有信号
receiver = nullptr断开所有接收者
member = nullptr断开所有槽函数
signal 和 receiver 均非空断开特定信号特定接收者所有槽
所有参数均非空断开特定信号特定接收者特定槽

使用场景示例

  1. 对象销毁前清理连接
    在析构函数中调用 disconnect(),确保对象销毁后无残留连接:

    ~MyObject() {
        disconnect(); // 断开所有连接
    }
  2. 临时断开信号
    在特定操作期间暂停信号传递,操作完成后重新连接:

    disconnect("dataChanged");
    // 执行批量操作...
    emit dataChanged(); // 手动触发信号
  3. 动态管理连接
    根据条件断开特定接收者的槽:

    if (condition) {
        disconnect(nullptr, receiver); // 断开所有信号到 receiver
    }

注意事项

  • 线程安全disconnect 是线程安全的,可在不同线程中调用。
  • 返回值:返回 bool 表示是否成功断开连接(至少有一个连接被断开时为 true)。
  • 性能:频繁调用可能影响性能,建议在必要时使用。

此重载通过参数默认值提供了极大的灵活性,是 Qt 信号槽机制中管理连接的重要工具。

9.QObject::disconnect的全部重载举例 qt 6.7 

下面是一个完整的示例,展示了如何在单个程序中实验 QObject::disconnect 的所有重载版本。这个示例使用 Qt 的信号和槽机制,通过不同的方式连接和断开信号与槽。

#ifndef SENDER_H
#define SENDER_H
#include <QCoreApplication>
#include <QObject>
#include <QDebug>

// 定义发送者类
class Sender : public QObject {
    Q_OBJECT
public:
    void emitValueChanged(int value) {
        emit valueChanged(value);
    }

signals:
    void valueChanged(int value);
};

// 定义接收者类
class Receiver : public QObject {
    Q_OBJECT
public slots:
    void onValueChanged(int value) {
        qDebug() << "Value changed to:" << value;
    }
};

#endif // SENDER_H
#include "Sender.h"

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    Sender sender;
    Receiver receiver1;
    Receiver receiver2;

    // 使用函数指针连接信号和槽
    QObject::connect(&sender, &Sender::valueChanged, &receiver1, &Receiver::onValueChanged);
    QObject::connect(&sender, &Sender::valueChanged, &receiver2, &Receiver::onValueChanged);

    // 发射信号,两个接收者都会响应
    qDebug() << "Emitting signal, both receivers should respond:";
    sender.emitValueChanged(10);

    // --------------------------------
    // 使用 disconnect 的重载版本
    // --------------------------------

    // 1. 断开特定信号和槽的连接
    QObject::disconnect(&sender, &Sender::valueChanged, &receiver1, &Receiver::onValueChanged);
    qDebug() << "Disconnected sender->receiver1. Emitting signal, only receiver2 should respond:";
    sender.emitValueChanged(20);

    // 2. 断开发送者的所有信号到特定接收者的连接
    QObject::disconnect(&sender, nullptr, &receiver2, nullptr);
    qDebug() << "Disconnected all signals from sender to receiver2. Emitting signal, no receivers should respond:";
    sender.emitValueChanged(30);

    // 3. 断开发送者的所有连接
    // 为了演示,这里重新连接信号和槽
    //删除全部信号源对应的链接
    QObject::connect(&sender, &Sender::valueChanged, &receiver1, &Receiver::onValueChanged);
    sender.disconnect();
    qDebug() << "Disconnected all connections from sender. Emitting signal, no receivers should respond:";
    sender.emitValueChanged(40);

    //删除信号源和某固定槽源的全部链接
    QObject::connect(&sender, &Sender::valueChanged, &receiver1, &Receiver::onValueChanged);
    sender.disconnect(&receiver1);
    qDebug() << "Disconnected all connections from sender. Emitting signal, no receivers should respond:";
    sender.emitValueChanged(50);

    return a.exec();
}

运行结果

16:12:54: Starting D:\projects\qts\untitled19\build\Desktop_Qt_6_7_2_MinGW_64_bit-Debug\untitled19.exe...
Emitting signal, both receivers should respond:
Value changed to: 10
Value changed to: 10
Disconnected sender->receiver1. Emitting signal, only receiver2 should respond:
Value changed to: 20
Disconnected all signals from sender to receiver2. Emitting signal, no receivers should respond:
Disconnected all connections from sender. Emitting signal, no receivers should respond:
Disconnected all connections from sender. Emitting signal, no receivers should respond:

代码说明

  1. Sender 类:定义了一个信号 valueChanged(int),并提供了一个方法 emitValueChanged(int) 来发射该信号。

  2. Receiver 类:定义了一个槽 onValueChanged(int),用于处理接收到的信号。

  3. main 函数

    • 创建 Sender 和两个 Receiver 对象。
    • 使用函数指针连接信号和槽。
    • 发射信号,并观察两个接收者的响应。
    • 使用 QObject::disconnect 的不同重载版本断开连接:
      • 断开特定信号和槽的连接。
      • 断开发送者的所有信号到特定接收者的连接。
      • 断开发送者的所有连接。
  4. 输出

    • 每次发射信号时,程序会输出哪些接收者响应了信号。
    • 通过断开连接,可以观察到接收者不再响应信号。

编译和运行

  • 确保你的项目文件(如 .pro 文件)中包含了 QT += core
  • 使用 qmake 和 make(或你的 IDE 的构建工具)编译项目。
  • 运行生成的可执行文件,观察输出。

这个示例展示了如何使用 QObject::disconnect 的不同重载版本,帮助你更好地理解信号和槽的连接和断开机制。

 

QMetaObject::invokeMethod: No such method QObject::gameOver()#include "gamecontroller.h" #include<QGraphicsScene> #include<QGraphicsView> #include<QEvent> #include<QKeyEvent> GameController::GameController(QGraphicsScene &scene, QObject *parent): QObject(parent), scene(scene), snake(new Snake(*this)) { timer.start(1000/33); Food *al=new Food(0,-50); scene.addItem(al); scene.addItem(snake); scene.installEventFilter(this); resume(); } void GameController::snakeAteItselt(Snake *snake){ QTimer::singleShot(0,this,SLOT(gameOver())); } void GameController::gameOver(){ scene.clear(); snake=new Snake(*this); scene.addItem(snake); addNewFood(); } void GameController::addNewFood(){ int x,y; do{ x=(int)(qrand()%100)/10; y=(int)(qrand()%100)/10; x*=10; y*=10; }while (snake->shape().contains(snake->mapFromScene(QPointF(x+5,y+5)))); Food *food=new Food(x,y); scene.addItem(food); } bool GameController::eventFilter(QObject *watched, QEvent *event){ if(event->type()==QEvent::KeyPress){ handleKeyPressed((QKeyEvent*)event); return true; }else { return QObject::eventFilter(watched,event); } } bool GameController::handleKeyPressed(QKeyEvent *event){ switch (event->key()) { case Qt::Key_Left: snake->setMoveDirection(Snake:: MoveLeft); break; case Qt::Key_Right: snake->setMoveDirection(Snake:: MoveRight); break; case Qt::Key_Up: snake->setMoveDirection(Snake:: MoveUp); break; case Qt::Key_Down: snake->setMoveDirection(Snake:: MoveDown); break; } } void GameController::pause() { disconnect(&timer,SIGNAL(timeout()),&scene,SLOT(advance())); } void GameController::resume() { connect(&timer,SIGNAL(timeout()),&scene,SLOT(advance())); } void GameController::snakeAteFood(Snake *snake, Food *food) { scene.removeItem(food); delete food; addNewFood(); } class QGraphicsScene; class QGraphicsView; class GameController:public QObject { public: GameController(QGraphicsScene &scene,QObject *parent); void snakeAteFood(Snake *snake,Food *food); void snakeAteItselt(Snake *snake); public slots: void pause(); void resume(); void gameOver(); protected: bool eventFilter(QObject *watched, QEvent *event); private: bool handleKeyPressed(QKeyEvent *event); void addNewFood(); QGraphicsScene &scene; QTimer timer; Snake *snake; };
07-19
QMetaObject::invokeMethod: No such method QObject::gameOver()#include "gamecontroller.h" #include<QGraphicsScene> #include<QGraphicsView> #include<QEvent> #include<QKeyEvent> GameController::GameController(QGraphicsScene *scene, QObject *parent): QObject(parent), scene(scene), snake(new Snake(*this)) { timer.start(1000/33); Food *al=new Food(0,-50); scene->addItem(al); scene->addItem(snake); scene->installEventFilter(this); resume(); } void GameController::snakeAteItselt(Snake *snake){ QTimer::singleShot(0,this,SLOT(gameOver())); } void GameController::gameOver(){ scene->clear(); snake=new Snake(*this); scene->addItem(snake); addNewFood(); } void GameController::addNewFood(){ int x,y; do{ x=(int)(qrand()%100)/10; y=(int)(qrand()%100)/10; x*=10; y*=10; }while (snake->shape().contains(snake->mapFromScene(QPointF(x+5,y+5)))); Food *food=new Food(x,y); scene->addItem(food); } bool GameController::eventFilter(QObject *watched, QEvent *event){ if(event->type()==QEvent::KeyPress){ handleKeyPressed((QKeyEvent*)event); return true; }else { return QObject::eventFilter(watched,event); } } bool GameController::handleKeyPressed(QKeyEvent *event){ switch (event->key()) { case Qt::Key_Left: snake->setMoveDirection(Snake:: MoveLeft); break; case Qt::Key_Right: snake->setMoveDirection(Snake:: MoveRight); break; case Qt::Key_Up: snake->setMoveDirection(Snake:: MoveUp); break; case Qt::Key_Down: snake->setMoveDirection(Snake:: MoveDown); break; } } void GameController::pause() { disconnect(&timer,SIGNAL(timeout()),scene,SLOT(advance())); } void GameController::resume() { connect(&timer,SIGNAL(timeout()),scene,SLOT(advance())); } void GameController::snakeAteFood(Snake *snake, Food *food) { scene->removeItem(food); delete food; addNewFood(); }
07-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值