是否可以在不删除 QObject 的情况下断开所有 QObject 的连接
Is it possible to disconnect all of a QObject's connections without deleting it
我有一个 QObject A,它连接到另一个 QObject B。现在我想让 A 连接到第三个 QObject C,并完全断开与 B 的连接。
轻松愉快!问题是我有很多 A,每个 A 都有自己的一组信号和槽(B's/C 更通用)。到目前为止,我一直在为每种不同的 class 类型手动创建连接和断开连接方法。这些方法基本上是彼此的副本,将 connect
交换为 disconnect
调用,与 don't repeat yourself).
相反
所以我的问题是:下面的功能是否可行?
void deleteAllConnections(QObject* someObject) {
// TODO disconnect all connections owned by someObject
// For bonus points: Is there a way of accessing the QMetaObject connected to?
}
我查阅了 QMetaObject, QObject and the Signals and Slots 文档,但没有成功(尽管这通常不能保证...)。
至少有两种方法。首先,断开所有连接。
disconnect(obj,0,0,0);
//or
obj->disconnect();
其次。每个 connect()
returns QMetaObject::Connection
都可以被复制或移动,所以你可以在列表中保存一些连接,一段时间后,只需遍历列表并调用 disconnect()
for每个对象。一个连接的示例:
QMetaObject::Connection m_connection;
//…
m_connection = QObject::connect(…);
//…
QObject::disconnect(m_connection);
奖励:不,Qt 不支持如此深入的内省,您无法获得所有已连接插槽的列表或其他内容,但在大多数情况下您根本不需要它。 Qt 为您提供的一个有用函数是 sender()
,它是指向发送信号的对象的指针。
编辑
正如 docs 所说:
Disconnect everything connected to an object's signals
因此在下一个示例中,windows 都将显示:
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
windows。这意味着 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");
我有一个 QObject A,它连接到另一个 QObject B。现在我想让 A 连接到第三个 QObject C,并完全断开与 B 的连接。
轻松愉快!问题是我有很多 A,每个 A 都有自己的一组信号和槽(B's/C 更通用)。到目前为止,我一直在为每种不同的 class 类型手动创建连接和断开连接方法。这些方法基本上是彼此的副本,将 connect
交换为 disconnect
调用,与 don't repeat yourself).
所以我的问题是:下面的功能是否可行?
void deleteAllConnections(QObject* someObject) {
// TODO disconnect all connections owned by someObject
// For bonus points: Is there a way of accessing the QMetaObject connected to?
}
我查阅了 QMetaObject, QObject and the Signals and Slots 文档,但没有成功(尽管这通常不能保证...)。
至少有两种方法。首先,断开所有连接。
disconnect(obj,0,0,0);
//or
obj->disconnect();
其次。每个 connect()
returns QMetaObject::Connection
都可以被复制或移动,所以你可以在列表中保存一些连接,一段时间后,只需遍历列表并调用 disconnect()
for每个对象。一个连接的示例:
QMetaObject::Connection m_connection;
//…
m_connection = QObject::connect(…);
//…
QObject::disconnect(m_connection);
奖励:不,Qt 不支持如此深入的内省,您无法获得所有已连接插槽的列表或其他内容,但在大多数情况下您根本不需要它。 Qt 为您提供的一个有用函数是 sender()
,它是指向发送信号的对象的指针。
编辑
正如 docs 所说:
Disconnect everything connected to an object's signals
因此在下一个示例中,windows 都将显示:
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
windows。这意味着 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");