能否在不删除QObject对象的情况下断开其所有连接?

38

我有一个QObject A,它连接到另一个QObject B。现在我想让A连接到C,第三个QObject,并完全断开与B的连接。

非常简单!问题是我有很多A,每个A都有自己的信号和槽集合(B/C更通用)。到目前为止,我一直在手动为每个不同的类类型制作连接和断开方法。这些方法基本上是相互复制,使用connectdisconnect调用进行交换,违反了不要重复自己的原则。

所以我的问题是:以下函数是否可行?


```cpp bool reconnect(QObject *sender, const char *signal, QObject *receiver, const char *method, QObject *oldReceiver, const char *oldMethod) ```
void deleteAllConnections(QObject* someObject) {
    // TODO disconnect all connections owned by someObject
    // For bonus points: Is there a way of accessing the QMetaObject connected to?
}

我在QMetaObjectQObjectSignals and Slots文档中搜索了一圈,但没有找到答案(尽管这通常不能保证...)。


QObject::disconnect(); - drescherjm
@drescherjm,该文档说明了“断开此对象中所有信号与接收器方法的连接”。我理解为它会断开对象中所有信号与其他对象的槽的连接,但我仍然不确定它是否也会断开其他对象的信号与对象的槽的连接。 - Troyseph
这是我的解决方案,只需保留对先前发送者的引用,并在需要时调用 disconnect - heLomaN
1个回答

75

至少有两种方法。首先,断开所有连接。

disconnect(obj,0,0,0);
//or
obj->disconnect();

其次,每个connect()函数都会返回一个QMetaObject::Connection对象,该对象可以被复制或移动,因此您可以将一些连接保存在列表中,过一段时间后,只需遍历列表并为每个对象调用disconnect()函数。以下是一个包含一个连接的示例:

QMetaObject::Connection m_connection;
//…
m_connection = QObject::connect(…);
//…
QObject::disconnect(m_connection);

奖励:不,Qt不支持如此深入的内省,你无法获得所有连接的槽的列表或其他任何东西,但在大多数情况下,你根本不需要这个。 Qt 给你一个有用的函数是 sender(),它是指向发送信号的对象的指针。

编辑

正如文档所说:

断开与对象的信号连接的所有内容

因此,在下一个示例中,两个窗口都将显示:

QWidget *a = new QWidget;
QWidget *b = new QWidget;

a->setWindowTitle("A");
b->setWindowTitle("B");

QObject::connect(a,SIGNAL(objectNameChanged(QString)), b, SLOT(show()));
QObject::connect(b,SIGNAL(objectNameChanged(QString)), a, SLOT(show()));

//a->disconnect();

a->setObjectName("A");
b->setObjectName("B");

但是如果取消注释a->disconnect();,那么只有A窗口将被显示。这意味着文档中所述的QObject::connect(b,SIGNAL(objectNameChanged(QString)),a,SLOT(show()));未被断开连接。如果要解决此难题,您可以执行a->disconnect(b); b->disconnect(a);,但这当然是非常糟糕的方法。因此,您可以使用我回答中的第二个建议:

QList<QMetaObject::Connection> connections;

QWidget *a = new QWidget;
QWidget *b = new QWidget;

a->setWindowTitle("A");
b->setWindowTitle("B");

connections << QObject::connect(a,SIGNAL(objectNameChanged(QString)), b, SLOT(show()));
connections << QObject::connect(b,SIGNAL(objectNameChanged(QString)), a, SLOT(show()));

foreach (auto var, connections) {
    QObject::disconnect(var);
}

a->setObjectName("A");
b->setObjectName("B");

很好的回答,断开所有连接是否包括入站和出站连接? - Troyseph
1
所以,这会断开所有的出站连接,但不包括入站连接,而这更为重要。 - 1313e

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接