Is it possible to disconnect all of a QObject's connections without deleting it

痞子三分冷 提交于 2019-12-04 16:34:41

问题


I have a QObject A, this is connected to another QObject B. Now I want A to connect to C, a third QObject and to completely disconnect from B.

Easy peasy! Trouble is I have a lot of of A's each with their own set of signals and slots (B's/C's are more generic). So far I have been manually making a connect and a disconnect method for each different class type. The methods are basically copies of each other exchanging the connect for disconnect call, going against the don't repeat yourself).

So my question is: Is the following function possible?

void deleteAllConnections(QObject* someObject) {
    // TODO disconnect all connections owned by someObject
    // For bonus points: Is there a way of accessing the QMetaObject connected to?
}

I've poked around in the QMetaObject, QObject and the Signals and Slots documentation with no luck (though that is often not a guarantee...).


回答1:


There are at least 2 ways. First, disconnect everything.

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

Second. Every connect() returns QMetaObject::Connection which can be copied or moved, so you can save some connections in the list and after some time, just iterate through the list and call disconnect() for every object. Example with one connection:

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

Bonus: no, Qt doesn't support such deep introspection, you can't get list of all connected slots or something another, but in most cases, you don't need this at all. One useful info, that Qt gives you is sender(), pointer to object that sent signal.

Edit

As doc said:

Disconnect everything connected to an object's signals

So in the next example both windows will be shown:

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");

But uncomment a->disconnect(); and only A windows will be shown. It means that QObject::connect(b,SIGNAL(objectNameChanged(QString)),a,SLOT(show())); was not disconnected as stated in the doc. If you want to solve this puzzle you can do a->disconnect(b);b->disconnect(a);, but it is of course very bad approach. So you can use second suggestion from my answer:

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");


来源:https://stackoverflow.com/questions/32124715/is-it-possible-to-disconnect-all-of-a-qobjects-connections-without-deleting-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!