ll_gzr
ll_gzr

Reputation: 109

QObject::connect: No such signal - QT and OpenCV SIGNAL and connect() error

I'm working on a computer vision project, an interactable surface that must handle user interactions through the video feed recognising the user's hands. The system recognizes the user's finger and map it on a GUI. I've developed the solution in Visual Studio 2017 using OpenCV for the video processing stuff, QT 5 to build the GUI and arduino to check the click on the surface. At the moment I've to controll a QTPushButton using the arduino serial output, that controll a boolean (isChecked) in the main class of the C++ program, I've read a lot about SIGNAL and SLOT in QT but when I trigger a SIGNAL using arduino serial connection and I handle the signal with connect() method in the MainWindow interface the system responds with the error : QObject::connect: No such signal QPushButton::valueChangedButton1(unsigned int).

The program failed to connect(button1, SIGNAL(valueChangedButton1(unsigned int)), this, SLOT(button1clicked()));, in the MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) instance.

SerialPort.h is an utility class to handle serial output from arduino. I've tried to put the connect() method in the while cycle of openCV but doesn't work.

MainWindow.h

#define NSAMPLES 7
#define ORIGCOL2COL COLOR_BGR2HLS
#define COL2ORIGCOL COLOR_HLS2BGR
#define PI 3.14159

#include <QtWidgets/QMainWindow>
#include <QtCore/qcoreapplication.h>
#include <QtGui/qtguiglobal.h>
#include <iostream>
#include "ui_MainWindow.h"
#include "opencv2/opencv.hpp"
#include "SerialPort.h"

    class MainWindow : public QMainWindow
    {

      Q_OBJECT

      public: 

           MainWindow(QWidget *parent = Q_NULLPTR); 

      private: 

           void initializationClicked(); 
           void stopCapture(); 
           void button1clicked(); 
           void button2clicked(); 

      signals: 

           void valueChangedButton1(unsigned int value);

      private:

        QPushButton *startCapture; 
        QPushButton *releaseCapture; 

        QPushButton *button1; 
        QPushButton *button2; 

        QLabel *interactionLabel;
        QLabel *interactionType; 
        QFont f, i; 
        char *PORT;
        bool b1Over, b2Over, isChecked; 

        // opencv stuff
        cv::VideoCapture cap; 
        cv::Mat src; 

        // arduino stuff
        char output[MAX_DATA_LENGTH];
        char incomingData[MAX_DATA_LENGTH];
        int intFromArduino;
        char *port;
        int fromArduino;
}

MainWindow.cpp

#include "MainWindow.h"

using namespace cv; 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)

{   

    f =  QFont("Arial", 12, QFont::Bold);
    i = QFont("Arial", 10, QFont::Black);

    PORT = "\\\\.\\COM5"; 

    width = 600; 
    height = 380; 

    setMinimumSize(width, height); 

    startCapture = new QPushButton("INIT SYSTEM", this);
    startCapture->setGeometry(QRect(QPoint(10, height - 120), QSize(100, 50)));
    connect(startCapture, SIGNAL(clicked()), this, SLOT(initializationClicked()));

    releaseCapture = new QPushButton("KILL SYSTEM", this);
    releaseCapture->setGeometry(QRect(QPoint(10, height - 60), QSize(100, 50)));
    connect(releaseCapture, SIGNAL(clicked()), this, SLOT(stopCapture()));

    button1 = new QPushButton("BUTTON 1", this);
    button1->setGeometry(QRect(QPoint(width / 2 - 100, height - 120), QSize(150, 100)));
    b1 = Point(width / 2 - 100, height - 120);  

    // receive the signal
    connect(button1, SIGNAL(valueChangedButton1(unsigned int)), this, SLOT(button1clicked()));

    button2 = new QPushButton("BUTTON 2", this);
    button2->setGeometry(QRect(QPoint(width / 2 + 100, height - 120), QSize(150, 100)));
    b2 = Point(width / 2 + 100, height - 120); 


    interactionLabel = new QLabel(this); 
    interactionLabel->setText("log: ");
    interactionLabel->setGeometry(QRect(QPoint(10, 15), QSize(200, 20))); 
    interactionLabel->setFont(f); 

    interactionType = new QLabel(this); 
    interactionType->setText("kind of interaction"); 
    interactionType->setGeometry(QRect(QPoint(110,15), QSize(250, 20)));
    interactionType->setFont(i);

}

void MainWindow::initializationClicked()
{
    controllMainVideoFlow(); 
}
void MainWindow::controllMainVideoFlow()
{
    SerialPort arduino(PORT); 
    cap = VideoCapture(0);
    if(!cap.isOpen())
    {
       cout << "no video feed" << endl; 
    }else
    {
       if(arduino.isConnected())
        {
           while(cap.isOpen())
          {
            cap >> src; 
            arduino.readSerialPort(output, MAX_DATA_LENGTH); 
            fromArduino = strlen(output); 
            if(fromArduino == 0)
            {
              isChecked = false; 
             }
            else if(fromArduino != 0)
             {
               isChecked = true;

               // emit the signal 
               emitSignalB1(); 
             }
          imshow("SOURCE", src); 

          qApp->processEvents();

          if (cv::waitKey(30) == 'q') break;
          }
       cap.release(); 
       src.release(); 
      }
    }
 }

void MainWindow::emitSignalB1()
{
    // emit the signal 
    emit valueChangedButton1(fromArduino);
}
void MainWindow::stopCapture()
{
    interactionType->setText("system killed");
    cap.release();
    src.release();
    destroyAllWindows(); 
}
void MainWindow::button1clicked()
{
    interactionType->setText("button 1 clicked");
}

void MainWindow::button2clicked()
{
    interactionType->setText("button 2 clicked");
}

Upvotes: 1

Views: 2707

Answers (1)

Fareanor
Fareanor

Reputation: 6805

The error is here:

connect(button1, SIGNAL(valueChangedButton1(unsigned int)), this, SLOT(button1clicked()));

Actually, there is no such signal called valueChangedButton1() in QPushButton. You get this error because button1 is a QPushButton.

You defined this signal in the MainWindow class, so you have to connect the signal from a MainWindow instance, not from a QPushButton instance.

You could write instead:

connect(this, SIGNAL(valueChangedButton1(unsigned int)), this, SLOT(button1clicked()));
//      ^
//      Not button1

This will fix your error.
But as it's not clear for me what you really want to do, I'm not sure if it is what you really want.


By the way, I think this is a typo but, in your header, you declared your signal as signal: instead of signals: (a 's' is missing).


EDIT: I would advise you to not use the old macros SIGNAL() and SLOT() anymore. You should use the new syntax instead.

Moreover, as the new syntax makes explicit from where the signals and slots are called, the origin of this error would have been obvious.

Upvotes: 3

Related Questions