Qt custom SLOT of subclass not recognised by CONNECT

864 views Asked by At

Background

I am writing a media player application in Qt. I have subclassed QMediaPlayer and created a new SLOT which is capable of interpreting an int and passing it as qint64 to QMediaPlayer::SetPosition(qint64).

QMediaPlayer::PositionChanged fires a signal to the cslider slider_playback (a horizontal slider subclass). This makes the slider move as a song is playedback. There are also some subclassed labels (clabel) which receive signals regarding the song duration and song playback position.

Problem

The problem i have occurs when I build & run, I receive the following error:

Starting /home/daniel/DeveloperProjects/build-Player-Desktop_Qt_5_9_1_GCC_64bit-Debug/Player...

QObject::connect: No such slot QMediaPlayer::set_playback_position(int) in ../Player/mainwindow.cpp:23

QObject::connect: (sender name: 'slider_playback')

The slider should be able to control the position of the playback. The offending line of code is preceeded by a '// Player seek' comment in the file.

I think the error indicates that the base class is being referred to for the SLOT, whereas the slots is actually part ofthe derived class.

Why is this error occuring and what action would resolve the issue? The slots in my clabel and cslider classes work without issue. The difference is that those classes have constructors and destructors. I have not implemented a constructor in the QMediaPlayer subclass as I do not want to override the base class constructor.

cmediaplayer.h (full file)

#ifndef CMEDIAPLAYER_H
#define CMEDIAPLAYER_H

#include <QMediaPlayer>
//#include <QObject>

class cmediaplayer : public QMediaPlayer
{
    Q_OBJECT

public slots:
    void set_playback_position(int);
};

#endif // CMEDIAPLAYER_H

cmediaplayer.cpp (full file)

#include "cmediaplayer.h"

void cmediaplayer::set_playback_position(int v) {
    this->setPosition( (qint64)v );
}

mainwindow.h (full file)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMediaPlayer>
#include "cmediaplayer.h"
#include "clabel.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
    QPalette m_pal;
    QString media_file_str="/usr/share/example-content/Ubuntu_Free_Culture_Showcase/Jenyfa Duncan - Australia.ogg";
    //QMediaPlayer * player ;
    cmediaplayer * player; // My custom type

private slots:
    void on_pushButton_pressed();
    void on_pushButton_released();
    void on_button_playback_clicked();
};

mainwindow.cpp (full file)

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow) {
    ui->setupUi(this);

    //player = new QMediaPlayer;
    player = new cmediaplayer; // My custom type

    // set max time on playback slider
    connect(player, SIGNAL(durationChanged(qint64)), ui->slider_playback, SLOT(set_qint64_max(qint64)));

    // st max time on playback label
    connect(player, SIGNAL(durationChanged(qint64)), ui->label_track_length, SLOT(setIntText(qint64)));

    // set slider playback position
    connect(player, SIGNAL(positionChanged(qint64)), ui->label_track_position, SLOT(setIntText(qint64)));


    // Player seek
    connect(ui->slider_playback,
        SIGNAL(valueChanged(int)),
        player,
        SLOT(set_playback_position(int)));


    // Player volume
    connect(ui->slider_volume,SIGNAL(valueChanged(int)),player,SLOT(setVolume(int)));
    ui->slider_volume->setValue(50); // set player initial value
}

MainWindow::~MainWindow() {
    delete ui;
    delete player;
    //delete playlist;
}

void MainWindow::on_pushButton_pressed() {
    m_pal=this->palette().color(QPalette::Background);
    QPalette pal=palette();
    pal.setColor(QPalette::Background,Qt::gray);
    this->setAutoFillBackground(true);
    this->setPalette(pal);

    player->setMedia(QUrl::fromLocalFile(media_file_str));
    player->setPlaybackRate(1);
    player->play();
}

void MainWindow::on_pushButton_released() {
    QPalette pal=m_pal;
    this->setAutoFillBackground(true);
    this->setPalette(pal);
    //player->stop();
}

void MainWindow::on_button_playback_clicked()
{
    //player->play();
}
2

There are 2 answers

1
eyllanesc On BEST ANSWER

Qt creates a new class that implements the actual connection between the slots and the signals but many times this one is not updated. The classes they refer to have a name similar to moc_xxx.cpp and these are created in the build folder.

To force them to update we must click on the make clean submenu that is located in the Menu Build of QtCreator, and then run qmake in the same menu.

Or you can manually remove the build folder and compile it back

1
Luighi Viton-Zorrilla On

Perhaps, it could help somebody. I had a similar issue when trying to use a SLOT function in the connect call. Even though the slot was declared and defined in the subclass, the connect function not recognize it, issuing a message which says that the slot function is not part of the base class.

In my case, the problem was that I didn't place the Q_OBJECT in the beginning of the class declaration. After that, I had to clean (otherwise, various errors occur in compilation step) and build the project again to had the slot function working properly.