Невозможно подключить сигнал к слоту в другом классе

У меня 2 класса. Класс A и класс B. Я испускаю сигнал от класса A, который я хочу получить от B.

Я делаю это следующим образом

В файле прослушивателя

Header File:
  Class Listener:public DDSDataReaderListener
  {
     //Some code
    public:
       A m_objectSendData;
  }

Файл реализации:

  void Listener::ondataavailable(DDSDataReader *reader)
 {
  m_objSendData.GetDDSData();
 }

В классе А

Заголовочный файл:

Class A:public QObject
{
  Q_OBJECT
  public:
    void GetDDSData();
  signals:
    void Signal_Data();
}

Файл .cpp

 A::A(QWidget *parent):QObject(parent)
{
}

void A::GetDDSData()
 {
   emit Signal_Data();
 }   

В классе Б

Header File:

  Class B:public QObject
  {
    Q_Object
    public:
    A objGetData;

    public slots:
    void getData();
  }

Implementation File:

 B::B(QWidget *parent):QObject(parent)
{
   //Some part of code

  connect(&objGetData,SIGNAL(Signal_Data()),this,SLOT(getData());
 }

 void B::getData()
 {
    //Watever is to be updated
  }

Я пробовал отладку. Он будет испускать часть правильно. Однако он не достигает слота. Может кто-нибудь, пожалуйста, помогите мне с этим. Спасибо.


person Sid411    schedule 07.08.2013    source источник
comment
Получаете ли вы какие-либо сообщения типа Object::connect: No such slot B::SlotB() при запуске приложения?   -  person thuga    schedule 07.08.2013
comment
Нет, это не показывает такое сообщение   -  person Sid411    schedule 07.08.2013
comment
Ну, я не вижу ничего плохого в коде, который вы разместили выше, за исключением отсутствующего ) перед ; в вашем выражении connect, но, очевидно, этого нет в вашем реальном коде.   -  person thuga    schedule 07.08.2013
comment
проверить логическое значение connect возвращается. Если это true, то соединение было успешным, и вы просто не излучаете сигнал. Если он возвращает false, проверьте ответ, который дал вам @Merlin069.   -  person Marek R    schedule 07.08.2013
comment
Еще одна вещь, вы не показали достаточно кода, но я подозреваю, что ваша программа выходит из области действия переменной objectA, и ваш испускающий объект просто уничтожается, прежде чем он сможет выдать какой-либо сигнал (objectA - это локальная переменная, созданная в стеке, а не в куче).   -  person Marek R    schedule 07.08.2013
comment
возможный дубликат сигнал C++ Qt и слот не срабатывает   -  person lpapp    schedule 14.06.2014


Ответы (2)


Без полного кода довольно сложно определить точную причину проблемы, поэтому я обозначу несколько важных моментов для проверки.

Чтобы убедиться, что вы можете использовать механизм сигналов и слотов, вы должны убедиться, что ваш класс является производным от QObject или классом, уже производным от QObject в своей иерархии, и ваш класс должен содержать макрос Q_OBJECT, например:

class A : public QObject // derived from QObject
{
    Q_OBJECT // your class must have this macro for signals and slots

    public:
    A();
};

Пропуск макроса, вероятно, является самой распространенной ошибкой.

Чтобы указать слот, вы добавляете его в раздел общедоступного или частного слота вашего класса:

class B : public QObject // derived from QObject
{
    Q_OBJECT // your class must have this macro for signals and slots

    public:
    B();

    public slots:
        void SlotB(); // slot declared public

    private slots:
        void SlotBPrivate(); // slot declared private.
}; 

Как только сигнал объявлен в классе, слот для приема сигнала должен соответствовать переданным аргументам, и когда вы подключаете сигнал к слоту, вы не должны добавлять имена аргументов функции.

Следовательно: -

connect(&objectA, SIGNAL(SignalA(int in), this, SIGNAL(SlotA(int param)); //will fail due to the argument names

Так должно быть: -

connect(&objectA, SIGNAL(SignalA(int), this, SIGNAL(SlotA(int));

Наконец, если вы используете Qt 5, вы можете использовать новый вызов соединения, который не требует от вас указания какого-либо аргумента, а вместо этого принимает адреса функций слота и сигнала.

connect(&objectA, &A::SignalA, this, &B::SlotA));

Поскольку он ссылается на адрес функции, на самом деле функции не нужно классифицировать как слоты, и они все равно будут вызываться.

Надеюсь, это поможет.

person TheDarkKnight    schedule 07.08.2013
comment
Я сделал точно так же. Я до сих пор не понимаю, в чем проблема. моя функция и слот являются общедоступными. - person Sid411; 07.08.2013
comment
Тогда не могли бы вы добавить к вопросу больше кода, например файлы заголовков, в которых вы объявляете слоты и сигналы. Также обратите внимание, что когда вы запускаете приложение с помощью отладчика и происходит сбой соединения, в окне вывода отображается ошибка. Пожалуйста, опубликуйте это тоже. - person TheDarkKnight; 07.08.2013
comment
Я объясню вам весь сценарий, что я делаю. У меня есть прослушиватель DDS, откуда я вызываю функцию QT. Из этой функции я испускаю сигнал, который идет в мой слот основного потока. Здесь я обновляю значения, поступающие из DDS. Я включил все заголовочные файлы, и писать в коде особо нечего. Это именно так, как я написал. Единственное дополнение, которое я могу сделать, это то, что в моем слушателе я создаю объект класса A и вызываю функцию. Это единственное, что я делаю в Listener. И во время отладки он говорит, что остановился на третьей точке останова, которая находится в операторе подключения. - person Sid411; 07.08.2013
comment
Извините, но хотя вы говорите, что включили весь свой код, вы явно этого не сделали, поскольку нет определения класса, нет макроса Q_OBJECT, нет сигналов или меток слотов и т. д. Хотя вы можете предположить, что предоставили вся необходимая информация, этого недостаточно. Вместо того, чтобы в вашем вопросе говорилось, например, В классе A..., вам нужно показать код, чтобы мы поняли его контекст и помогли вам решить проблему, с которой вы столкнулись. Я мог бы показать вам код a = 4 и сказать, что он дает сбой, но без вашего знания того, что такое 'a', и окружающего его кода, вы понятия не имеете, почему. - person TheDarkKnight; 07.08.2013

На самом деле я считаю, что ответ дан в одном из комментариев.

Еще одна вещь, вы не показали достаточно кода, но я подозреваю, что ваша программа выходит из области действия переменной objectA, и ваш испускающий объект просто уничтожается, прежде чем он сможет выдать какой-либо сигнал (objectA - это локальная переменная, созданная в стеке, а не в куче). – Марек Р. 1 час назад

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

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

person evilruff    schedule 07.08.2013
comment
Я использую его как переменную-член, но он не работает. Так что в этом случае он должен идти в кучу. Я отредактирую и напишу полный код. - person Sid411; 07.08.2013
comment
Я думаю, что проблема в том, что мой средний класс не является классом-одиночкой. Я попробую сделать его синглтоном, а затем отредактирую решение здесь... - person Sid411; 07.08.2013