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

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

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, все будет работать нормально, но мне интересно, почему приведенное выше решение не сработает.


person M F    schedule 30.08.2017    source источник
comment
parentWidget не похоже на тип MainWindow.   -  person m7913d    schedule 30.08.2017
comment
Сейчас самое время начать использовать новый синтаксис сигнального слота, представленный в Qt 5; таким образом вы получите более четкую ошибку во время компиляции.   -  person MrEricSir    schedule 30.08.2017
comment
Если я использую новый синтаксис сигнального слота, моя программа вылетает из-за ошибки сегментации в методе слота класса MainWindow.   -  person M F    schedule 31.08.2017


Ответы (3)


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

person sisco_0    schedule 30.08.2017

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

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

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

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

person WindyFields    schedule 31.08.2017

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

person M F    schedule 31.08.2017