Соединение сигнала/слота Qt не работает

У меня очень странная проблема с методом QObject::connect. Сначала взгляните на этот очень простой код:

class B : public QWidget {
  Q_OBJECT
public:
  explicit B(QWidget* parent = 0) : QWidget(parent) { }
signals:
  void event();
}

class A : public QObject {
  Q_OBJECT
public:
  explicit A(QWidget* parent = 0) : QObject(parent) { b = new B(parent); init(); }
  void init() { QObject::connect(b, SIGNAL(event()), this, SLOT(handler())); }
public slots:
  void handler() { /*spit out some text*/ }
private:
  B* b;
}

Объект A не отвечает на сигналы, исходящие от объекта B. Я уверен, что сигнал излучается, как и ожидалось. Метод QObject::connect возвращает true, что указывает на успех. Я запустил qmake, moc, и файлы moc_.cpp* кажутся правильными.

Интересно, где я сделал ошибку?

Редактировать I:

Вот код, над которым я работаю, он урезан, поэтому показаны только соответствующие части:

class ListController : public QObject {
  Q_OBJECT
public:
  explicit ListController(Model* model, QWidget* parent = 0) : QObject(parent) { compositeView = new CompositeView(parent); initConnections(); }
  void initConnections() { QObject::connect(compositeView->getListView(), SIGNAL(event()), this, SLOT(handler())); }
public slots:
  void handler() { qDebug()<<"signal is received ..."; }
private:
  CompositeView* view;
};

class CompositeView: public QGroupBox {
  Q_OBJECT
public:
  explicit CompositeView(QWidget* parent = 0) : QGroupBox(parent) { listView = new ListView(this); }
  ListView* getListView() const { return listView; }
private:
  ListView* listView;
};

class ListView : public QListWidget {
  Q_OBJECT
public:
  explicit ListView(QWidget* parent = 0) : QListWidget(parent) { }
protected:
  void dropEvent(QDropEvent *event) { emit signal(); }
signals:
  void signal();
};

Я создаю новый объект ListController внутри подкласса QWidget, передавая себя в качестве родителя и предоставляя соответствующий объект Model.

Изменить II

ListController возвращает объект CompositeView в главный виджет. основной виджет добавляет составной вид к своему макету. В этот момент родитель CompositeView и его дочерние элементы изменены. Что может быть источником проблемы.


person Y.H.    schedule 04.04.2012    source источник
comment
Ваш код выглядит правильно. Вы сказали, что уверены, что сигнал излучается - как вы проверили?   -  person laurent    schedule 04.04.2012
comment
ответив на сигнал другого подкласса QWidget. Кстати, я использую SKD версии 4.8.   -  person Y.H.    schedule 04.04.2012
comment
Возможно, код в handler() делает то, что вы думаете. Вы можете это показать?   -  person Arnold Spence    schedule 04.04.2012
comment
Получен сигнал qDebug()‹‹...;   -  person Y.H.    schedule 04.04.2012
comment
Вы пытались удалить все файлы сборки, а затем очистить и перестроить проект?   -  person laurent    schedule 04.04.2012
comment
Да, очистить, а затем восстановить, все еще не работает.   -  person Y.H.    schedule 04.04.2012
comment
Можете ли вы включить минимальный пример того, как используются классы? Из этого кода я не вижу ничего плохого.   -  person tmpearce    schedule 04.04.2012
comment
Я отредактировал пост и добавил соответствующие части кода   -  person Y.H.    schedule 04.04.2012
comment
Я бы предположил, что getListView() действительно реализовано. Также, когда вы пытаетесь запустить приложение, оно жалуется, что не может установить соединение? В Linux он просто сбрасывал его в stderr.   -  person Karlson    schedule 04.04.2012
comment
Извините, забыл написать, просто добавил. Как ни странно, я не получаю никаких жалоб во время компиляции. Во время выполнения, когда слот не найден или написан с ошибкой, он записывается на консоли. Я тоже не получаю таких жалоб.   -  person Y.H.    schedule 04.04.2012
comment
Вы используете virtual void QListWidget::event(QEvent*) или перегружаете эту функцию, чтобы она не принимала аргументы?   -  person tmpearce    schedule 04.04.2012
comment
Нет, это просто произвольное имя, но у меня вопрос, можно ли получить сигнал от произвольного класса? то есть, если сигнал исходит от объекта, может ли другой объект из другой иерархии получить сигнал и воздействовать на него?   -  person Y.H.    schedule 04.04.2012
comment
Да, они не обязательно должны находиться в одной иерархии или вообще в иерархии — они просто являются производными от QObject. Две идеи: 1) попробуйте переименовать свой метод event во что-то другое (например, myEvent). 2) Убедитесь, что объект, который должен получать сигнал, не уничтожен до того, как сигнал будет отправлен (добавьте сообщение печати в деструктор).   -  person tmpearce    schedule 04.04.2012
comment
@H.Josef Подписи signal и slot должны совпадать. И если вы на самом деле повторно реализуете сигнал, лучше объявить его как signal просто для вашей ясности.   -  person Karlson    schedule 04.04.2012
comment
Спасибо за ответы, однако я не совсем уверен в этом. Вы видите, что signal в конце концов является защищенным методом, я не думаю, что можно вызывать такой метод из другой иерархии.   -  person Y.H.    schedule 04.04.2012
comment
signal — это метод. Объект, у которого есть этот метод, вызывает его; signal вызывает любой подключенный slots. Таким образом, доступ не является проблемой в конце концов. Подключение к защищенным/приватным слотам — это отдельная история.   -  person tmpearce    schedule 04.04.2012
comment
хм... но после того, как я добавлю объект CompositeView в макет основного виджета, я могу заставить основной виджет реагировать на этот неприятный сигнал.   -  person Y.H.    schedule 04.04.2012
comment
возможно, где бы вы ни использовали объект раньше, он не был доступен /part основного цикла событий?   -  person tmpearce    schedule 04.04.2012
comment
Я так не думаю, потому что я пытался восстановить связь между контроллером и виджетом после того, как виджет был добавлен в макет, и все равно ничего не вышло...   -  person Y.H.    schedule 05.04.2012


Ответы (2)


Ответ на эту проблему оказался намного проще, чем я ожидал.

Я думаю, что сделал ошибку, выполнив следующие шаги:

  1. ListController создается в стеке.
  2. Объект CompositeView возвращается и добавляется к основному макету виджета.
  3. ListController объект молча выходит из области видимости и уничтожается, а следовательно, и соединение.

Комментарий 13 сверху был фактически решением. Большое спасибо tmpearce за совет.

person Y.H.    schedule 04.04.2012

singals:
  void signal();

Я сомневаюсь, что если это фактический код, с которым вы работаете, проверьте ошибку опечатки.

person Soumya Kundu    schedule 04.04.2012
comment
Спасибо soumya за подсказку, это действительно опечатка, ее нужно исправить, иначе будет ошибка компиляции, но кроме этого типа (который я исправлю) в чем здесь проблема, я так и не могу понять... - person Y.H.; 05.04.2012