Временно заблокировать сигналы между двумя объектами QObject.

Я хотел бы вообще и временно заблокировать сигналы между двумя QObjects без изменения поведения других сигналов/слотов и без знания их контекстов.

Что-то вроде QObject::blockSignals(bool), но только действующий между двумя QObjects.

То есть реализация следующей функции SignalBlocker::blockSignals(bool):

class SignalBlocker {

public:
  SignalBlocker(QObject *sender, QObject *receiver) :
    mSender(sender), mReceiver(receiver) {}
  void blockSignals(bool block);

private:
  QObject *mSender, *mReceiver;
}

Это было бы возможно путем отключения и повторного подключения объектов, но сначала необходимо было бы сохранить список сигналов/слотов. Методы самоанализа не кажутся достаточно мощными для достижения этой цели (я безуспешно смотрел на QMetaObject и QSignalSpy).


person FabienRohrer    schedule 26.03.2013    source источник


Ответы (3)


QT не имеет возможности отключать только пару сигнал-слот. Попробуйте этот обходной путь:

struct SignalDisabler
{
    SignalDisabler(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
        : sender(sender)
        , signal(signal)
        , receiver(receiver)
        , member(member)
    {
        QObject::disconnect(sender, signal, receiver, member);
    }

    ~SignalDisabler()
    {
        QObject::connect(sender, signal, receiver, member);
    }

    const QObject *sender;
    const char *signal;
    const QObject *receiver;
    const char *member;
};
person Oleg    schedule 22.06.2013

поскольку вы хотите, чтобы отправитель и получатель не отправляли сигналы в этой области, я бы просто попытался использовать blockSignals(bool)

class SignalBlocker{
public:
SignalBlocker(QObject* obj)
{
   _o = obj;
   _o->blockSignals(true);
}
~SignalBlocker()
{
   _o->blockSignals(false);
}
private:
   QObject* _o;
};

а теперь просто используйте

SignalBlocker sb1(sender);
SignalBlocker sb2(reciever);
//...
person Zaiborg    schedule 26.03.2013
comment
К сожалению, мою проблему это все равно не решает, потому что отправитель и получатель в этом случае полностью заблокированы (они не могут отправлять сообщения третьему QObject, а мне это нужно). - person FabienRohrer; 03.04.2013
comment
возможно, можно создать класс, подобный SignalBlocker, и дать объектам указатель функции шаблона того, что вы хотите заблокировать... так что он будет блокировать только тот сигнал, который вы хотите - person Zaiborg; 03.04.2013

Вы можете использовать disconnect(sender, 0, receiver, 0); для отключения всех сигналов sender от всех слотов receiver.

person SpongeBobFan    schedule 26.03.2013
comment
Действительно, но я хотел бы иметь возможность получить то же состояние, что и до отключения при повторном подключении Объекта. Поэтому перед отключением я должен перечислить все соединения сигналов/слотов между отправителем и получателем (и это то, что я не могу сделать). - person FabienRohrer; 26.03.2013
comment
Попробуйте использовать что-то вроде void QObject::connectNotify ( const char * signal ) [virtual protected] или void QObject::disconnectNotify ( const char * signal ) [virtual protected], чтобы получить список подключенных/отключенных сигналов, но я не думаю, что вы делаете правильные вещи. Зачем тебе это надо? - person SpongeBobFan; 26.03.2013