c++ - Qt 线程中未检测到信号和插槽

标签 c++ multithreading qt opencv

我正在 Qt 中创建一个简单的应用程序用于学习目的。我想显示网络摄像头捕获的图像,以显示在我的用户界面 (ui) 的图形 View 中。

功能:按下开始按钮时,网络摄像头帧开始显示在图形 View 中。当按下暂停按钮时,网络摄像头流式传输将暂停。最后,如果按下退出按钮,整个应用程序将终止。

我的方法:我想在按下开始按钮时启动一个 Qt 线程,该线程将连续捕获网络摄像头帧。捕获每个网络摄像头帧后,该线程将发出一个信号并将指针传递给捕获图像的数据、高度和宽度。此信号将连接到 MainWindow 类的插槽(即 setGraphicsView())。 MainWindow 类的 slot 会将捕获的网络摄像头图像分配给 ui 的 GraphicsView。

我的代码:

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow *w = new MainWindow;
    w->show();

    return a.exec();
}

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

//Threading
#include "thread.h"

//OpenCV
#include <opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/opencv.hpp"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:

    void on_StartButton_clicked();

    void on_PauseButton_clicked();

    void on_QuitButton_clicked();
    void setGraphicsView(unsigned char* ptrWebcamImg, int iw, int ih);

private:
    Ui::MainWindow *ui;
    Thread guiThread;
};

#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsPixmapItem>

using namespace cv;

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QObject::connect(ui->StartButton, SIGNAL(clicked()), &guiThread, SLOT(start()), Qt::QueuedConnection);
    //When the thread emits a signal saying it has got a new webcam frame, reflect that change in the graphicsview of ui.
    QObject::connect(&guiThread,SIGNAL(signalGotNewFrame(const unsigned char* ptrWebcamImage, int iw, int ih)),this,SLOT(setGraphicsView(const unsigned char* ptrWebcamImage, int iw, int ih)), Qt::QueuedConnection);
    QObject::connect(ui->PauseButton, SIGNAL(clicked()), &guiThread, SLOT(stopRunning()), Qt::QueuedConnection);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setGraphicsView(unsigned char *ptrWebcamImg, int iw, int ih)
{
    Mat frame(ih, iw, CV_8UC3, Scalar(0,0,255));

    //Conver the Mat frame into QImage and assign it to the GraphicsView of ui.
    QImage image( frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888 );
    QGraphicsScene* scene = new QGraphicsScene();
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
    scene->addItem(item);
    ui->graphicsView->setScene(scene);
}

void MainWindow::on_StartButton_clicked()
{
}

void MainWindow::on_PauseButton_clicked()
{
    //guiThread.stopRunning();
}

void MainWindow::on_QuitButton_clicked()
{
    connect(ui->QuitButton,SIGNAL(released()), qApp, SLOT(quit()));
}

thread.h

#ifndef THREAD_H
#define THREAD_H

#include <QThread>

class Thread : public QThread
{
    Q_OBJECT

public slots:
    void stopRunning();
    //virtual void run();
protected:
    virtual void run();
private:
    bool isWebcamNeeded;
signals:
    void signalGotNewFrame(unsigned char* ptrFrame, int iw, int ih);

};


#endif // THREAD_H

线程.cpp

#include "thread.h"

//Qt and
#include <QGraphicsPixmapItem>
#include <iostream>

//OpenCV related
#include <opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;

void Thread::run()
{
    std::cout<<"\nIn the thread"<<std::endl;
    isWebcamNeeded = true;
    cv::VideoCapture cap(0);
    Mat frame;
    unsigned char *ptrFrame;
    while(isWebcamNeeded == true) //"this->isWebcamNeeded" will become false when PauseButton will be clicked
    {
        cap >> frame;
        ptrFrame = frame.data;
        emit signalGotNewFrame(ptrFrame, frame.cols, frame.rows);
    }
}

void Thread::stopRunning()
{
    isWebcamNeeded = false;
}

问题:我收到以下运行时错误:

QObject::connect: No such signal Thread::signalGotNewFrame(const unsigned char* ptrWebcamImage, int iw, int ih) in ../MyCamApp/mainwindow.cpp:12
QObject::connect:  (receiver name: 'MainWindow')

最佳答案

这段代码有很多问题!

  1. 这里不需要线程。 QTimer 是更好更安全的解决方案(你会犯更少的错误)
  2. 子类QThread is bad approach when handling threads (我不会解释为什么,因为你不应该使用它们)。
  3. 您的信号是插槽定义错误,这将导致内存管理出现问题。
  4. cv::MatQPixmap的转换方法是a bit more complicated
  5. 您尝试在 QGraphicsView 上显示它的方式完全错误。你应该read documentation how to use this part of Qt .

归根结底,要使一切正常运行,您还有很长的路要走。海事组织你应该退后几步,从更简单的事情开始。目前,您在很多领域(至少 3 个)缺乏技能,因此学习任何东西对您来说都是非常痛苦的。一次提高一个新领域的技能。

关于c++ - Qt 线程中未检测到信号和插槽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32938085/

相关文章:

c++ - LZZ 语法错误 for typedef enum _foo { a } foo;

c++ - boost 图形库 : access violation in reading from adjacency_list in parallel mode

c++ - 智能指针作为 QObject::deleteLater() 的替代品

qt - QLineEdit 光标在 textChanged() 或 commitData() 之后移动到结束

c++ - 未定义的类引用错误

c++ - 程序能否计算出其 Oracle 资源使用情况?

c++ - 转储原始图像数据

java - 如何将类对象传递给 jni native 方法

multithreading - 确定机器上可用核心的数量?

JavaFx,多线程应用程序,奇怪的异常