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

У меня есть следующие классы:

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QStringList pluginsToStart, QWidget *parent = 0);
    ~MainWindow();

// some other stuff

public slots:
    void on_timeDataChanged(logging::TimeValueVector<bool>& aData);
    void on_importStarted();
}

а также

class DataImporterWidget : public PluginWidget
{
    Q_OBJECT

public:
    explicit DataImporterWidget(QWidget *parent = 0);
    ~DataImporterWidget();

    void initConnections(QMap<QString, PluginWidget*> pluginWidgetMap);

в методе initConnections я хочу, чтобы виджет инициировал соединения с сигнальными слотами следующим образом:

void DataImporterWidget::initConnections(QMap<QString, PluginWidget*> pluginWidgetMap)
{
    for(Importer* importer : this->getImporterMap().values())
    {
        connect(importer, SIGNAL(signal_timeDataChanged(logging::TimeValueVector<bool>&)),
            parentWidget(), SLOT(on_timeDataChanged(logging::TimeValueVector<bool>&)));
    }

    connect(this, SIGNAL(signal_importStarted()), parentWidget(), SLOT(on_importStarted()));
}

Importer - это QGroupBox и базовый класс для производных подклассов, определяющих конкретные типы средств импорта данных. Это работает так: если я нажимаю кнопку, создается DataImporterWidget и добавляется в QMdiArea как QMdiSubWindow. При создании DataImporterWidget я вызываю метод initConnections(), который устанавливает соединения сигнальных слотов.

Теперь, когда я запускаю программу, я получаю следующее сообщение:

QObject::connect: No such slot 
QMdiSubWindow::on_timeDataChanged(logging::TimeValueVector<bool>&) in src/dataimporter/DataImporterWidget.cpp:81
QObject::connect: No such slot QMdiSubWindow::on_importStarted() in src/dataimporter/DataImporterWidget.cpp:85
QObject::connect:  (sender name:   'DataImporterWidget')

Я не понимаю, почему я получаю это, потому что слот там. Даже если я приведу parentWidget к MainWindow, я получаю ту же ошибку.

PluginWidget - это просто базовый класс, производный от QWidget, который содержит некоторые общие функции для моих используемых плагинов. Я положил Q_OBJECT на каждый базовый и производный класс, но все равно получаю эту ошибку. Тем не менее, если я настрою соединения в MainWindow, все будет работать нормально, но мне интересно, почему вышеприведенное решение не будет работать.

3 ответа

Решение

Я нашел проблему. Причина в том, что класс MainWidget содержит QMdiArea, куда я добавляю свои PluginWidgets. Поэтому, когда я создаю PluginWidget, я устанавливаю MainWidget в качестве его родителя, но как только я добавляю его в QMdiArea, он также становится дочерним для QMdiSubWindow. ParentWidget никогда не был нулевым, но он был неправильным...

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

Вы не показали огромный кусок важного кода (например, создание DataImporterWidget, настройка MainWindow как его родитель, место, где вы звоните initConnections...). Тем не менее, вы сказали

Если я использую новый синтаксис сигнального слота, моя программа падает с ошибкой сегментации...

Если это терпит крах, тогда вы должны найти причину. Использование старого синтаксиса соединения "сигнал-слот" не излечивает болезнь, а просто задерживает ее проявление. Согласно этому, причина, почему вы получаете segfault может быть parentWidget() == nullptr или же parent еще не инициализирован.

Мой совет, проверь свой код и сделай пользователя родителем DataImporterWidget создан и указан до вашего звонка initConnections(),

Другие вопросы по тегам