web-dev-qa-db-ja.com

QObjectのすべての接続を削除せずに切断することは可能ですか?

QObject Aがあり、これは別のQObject Bに接続されています。次に、Aを3番目のQObjectであるCに接続し、Bから完全に切断するようにします。

簡単!問題は、それぞれに独自の信号とスロットのセットを持つAが多数あることです(B/Cはより一般的です)。これまでのところ、異なるクラスタイプごとに手動で接続および切断メソッドを作成しています。メソッドは基本的に、connectdisconnect呼び出しに交換する相互のコピーであり、 繰り返しはしないでください )に反します。

だから私の質問は次のとおりです。次の機能は可能ですか?

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

私は QMetaObjectQObject 、および Signals and Slots のドキュメントを不運にもつつきました(多くの場合、これは保証ではありませんが.. 。)。

22
Troyseph

少なくとも2つの方法があります。まず、すべてを切断します。

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

第二に。すべてのconnect()_QMetaObject::Connection_ を返します。これはコピーまたは移動できます。そのため、リストに接続を保存し、しばらくしてからリストを反復してdisconnect()すべてのオブジェクトに対して。接続が1つの例:

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

ボーナス:いいえ、Qtはこのような深いイントロスペクションをサポートしていません。接続されているすべてのスロットなどのリストを取得することはできませんが、ほとんどの場合、これはまったく必要ありません。 Qtが提供する便利な情報の1つは、信号を送信したオブジェクトへのポインターsender()です。

編集

doc のように:

オブジェクトの信号に接続されているすべてを切断します

したがって、次の例では両方のウィンドウが表示されます。

_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);を実行できますが、もちろん非常に悪いアプローチです。だからあなたは私の答えから2番目の提案を使うことができます:

_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");
_
46
Chernobyl