2012-03-05 18 views
2

信号Sを送信するクラスCがあります。Sはゼロ、1つ以上のレシーバ(R)(接続数は時間とともに変化し、connectionswは受信機によって作られる)。Qt disconnectNotify()はレシーバオブジェクトの破棄で呼び出されません

Cは、Sのリスナーの数が0より大きくなると、Sのリスナーの数が0に戻ったときに他の処理を行う必要があります。

私は、私が使用できることを考えた:

connectNotify() 

disconnectNotify() 

だけでなく、私が気づく何

はconnectNotify()関数がうまく機能していることですが、 disconnectNotify()は、受信オブジェクトが破棄されたときに(クラスC内で)呼び出されません。 disconnect()を使用した明示的な切断が使用された場合にのみ呼び出されます。

リスナーのデストラクタで明示的な切断を追加すると、アプリケーション全体を終了するときにセグメンテーション違反が発生することもありませんでした。 (すべてがダウンしているときにdisconnect()を使うのは良いことではないでしょう)

Rが破壊されたときにRインスタンスからCに送られたdestroy()シグナルを使用しようとしました。 Rが破壊時に接続されたことをどうすれば確認できますか? (受信者Rは非接続状態で存在する可能性があります):

クラスCでは、スロットX(R's destroyed()の受信時に呼び出されます)では、QObject :: receivers()をチェックすると受信者数が返されているようです破壊が行われる。破壊されているオブジェクトが接続されているかどうかわからないので、私は立ち往生しています!

アイデア?あなたは、すべてのRは、Cの前に破壊されていることを確認できた場合は

+0

私はテストアプリで同じ動作を取得します。これは私のドキュメントと矛盾しているようです。デストラクタで明示的に切断するという考えは私にとってはうまくいくが、プログラム内の破壊の順序は物事を乱すかもしれない。信号の受信者が破壊されたときに誰かが 'disconnectNotify'を得ることができるかどうかを知りたいのです。 – tmpearce

+0

これはQt 5で修正されています。[QTBUG-4844](https://bugreports.qt-project.org/browse/QTBUG-4844)を参照してください。 – Oktalist

答えて

1

、あなたはクラスCに接続を自分で管理することができます:

ヘッダファイル:

#include <QtCore/QSet> 

class C : (...) 
{ 
    (...) 

public: 
    void connectReceiver(QObject* receiver); 

private slots: 
    void handleReceiverDestruction(QObject* receiver); 

private: 
    QSet< QObject* > _connectedReceivers; 
}; 

ソースファイル:

void C::connectReceiver(QObject* receiver ) 
{ 
    // nothing to do if the receiver is already connected 
    if(_connectedReceivers.contains(receiver )) return; 

    _connectedReceivers.append(receiver) 

    connect(...); // <- do your connection(s) here 
    connect(receiver, SIGNAL(destroyed    (QObject*)), 
      this , SLOT (handleReceiverDestruction(QObject*))); 
} 

void C::handleReceiverDestruction(QObject* receiver) 
{ 
    if(!_connectedReceivers.contains(receiver)) 
    { 
     // if this happens, a receiver R's destroyed() signal was connected to 
     // this function altough R is not a receiver of signal X. 
     Q_ASSERT(false); 
     return; 
    } 

    disconnect(...); // <- one or more might be necessary here 

    _connectedReceivers.remove(receiver); 
} 

ヒント:コンパイルや論理エラーのためにこれをテストしませんでしたが、そのアイディアを得るべきです。

個人的に、私は多分、以下を追加します。

C::~C() 
{ 
    if(!_connectedReceivers.isEmpty()) 
    { 
     // If you land here, a receiver was not (properly) destroyed before this object 
     Q_ASSERT(false); 
    } 
} 
+0

ありがとう、 これは私が回避策としてやったことに非常に近いです。 QObject :: receivers()は、受信者が破棄されたときに減少するように見えるので、QOBject :: receivers()を時々チェックしています(ただし、Cでdestroyed()シグナルを受け取った後に発生します)。それらは多くの可能な回避策ですが、私はまだdisconnectNotifyの動作が奇妙であると感じています。 もう一度ありがとう! – user1159290

関連する問題