c++ - Qt:信号槽不工作

标签 c++ multithreading qt qthread qt-signals

我正在尝试在主 gui 和移动到另一个线程的另一个对象之间实现信号和插槽系统...以下是类设计的样子...不幸的是无法实现它...

主窗口.h

signals:
    void StopDisplayWidget();
    void StartDisplayWidget();
    void signalFromGUI();

private slots:
    void on_pushButton_start_display_clicked();

    void on_pushButton_stop_display_clicked();

    void on_pushButton_check_clicked();

private:
    Ui::MainWindow *ui;
    displaythread *threadforDisplay;
    display *displayWidget;
    QThread *WorkerDisplay;

主窗口.cpp

{
    threadforDisplay = new displaythread;
    threadforDisplay->setptr2display(displayWidget);

    WorkerDisplay = new QThread;
    QObject::connect(WorkerDisplay,SIGNAL(started()),threadforDisplay,SLOT(Process()));

    QObject::connect(this,SIGNAL(StartDisplayWidget()),threadforDisplay,SLOT(StartDisplay()));
    QObject::connect(this,SIGNAL(StopDisplayWidget()),threadforDisplay,SLOT(StopDisplay()));
    QObject::connect(this,SIGNAL(signalFromGUI()),threadforDisplay,SLOT(Check()));

    threadforDisplay->moveToThread(WorkerDisplay);
}

void MainWindow::on_pushButton_start_display_clicked()
{
    if(!threadforDisplay->IsDisplayActive())
        emit this->StartDisplayWidget();

    if(!WorkerDisplay->isRunning())
        WorkerDisplay->start();
}

void MainWindow::on_pushButton_stop_display_clicked()
{
    if(threadforDisplay->IsDisplayActive())
    {
        emit this->StopDisplayWidget();
    }
}

void MainWindow::on_pushButton_check_clicked()
{
    std::cout<<"CHECKING SIGNAL SLOT"<<std::endl;
    emit this->signalFromGUI();
}

threadforDisplay 是指向displaythread 类 的指针

显示线程.h

#include <QObject>
#include <QWaitCondition>
#include <QMutex>
#include "display.h"

class displaythread : public QObject
{
    Q_OBJECT
public:
    explicit displaythread(QObject *parent = 0);
    bool IsDisplayActive() const;
    void setptr2display(display *);

signals:

public slots:
    void Process();
    void StartDisplay();
    void StopDisplay();
    void Check();


private:
    void SleepThread();

    volatile bool stopped,running;
    QMutex mutex;
    QWaitCondition waitcondition;
    display *displayinGUI;

显示线程.cpp

void displaythread::setptr2display(display *ptr)
{
    displayinGUI = ptr;
}

void displaythread::Process()
{
    std::cout<<"RECEIVED START PROCESS SIGNAL"<<std::endl;
    running = true;
    while(true)
    {
        if(!stopped)
        {
            displayinGUI->update();
            this->SleepThread();
        }
    }

}

void displaythread::SleepThread()
{
    mutex.lock();
    waitcondition.wait(&mutex,20);
    mutex.unlock();
}

void displaythread::StartDisplay()
{
    std::cout<<"RECEIVED START SIGNAL"<<std::endl;
    stopped = false;
    running = true;
}

void displaythread::StopDisplay()
{
    std::cout<<"RECEIVED STOP SIGNAL"<<std::endl;
    stopped = true;
    running = false;
}

bool displaythread::IsDisplayActive() const
{
    return running;
}

void displaythread::Check()
{
    std::cout<<"SIGNAL FROM GUI RECEIVED"<<std::endl;
}

display.h

class display : public QWidget
{
    Q_OBJECT
public:
    explicit display(QWidget *parent = 0);
    ~display();

signals:

public slots:

private:
    void paintEvent(QPaintEvent *);

    IplImage *image_opencvBGR,*image_opencvRGB;
    QImage image;
    CvCapture *webcam;

显示.cpp

display::display(QWidget *parent) :
    QWidget(parent)
{
    image_opencvRGB = cvCreateImage(cvSize(640,480),8,3);
    webcam = cvCaptureFromCAM(-1);
}

display::~display()
{
    cvReleaseCapture(&webcam);
}

void display::paintEvent(QPaintEvent *)
{
    //std::cout<<"IN PAINT LOOP"<<std::endl;
    image_opencvBGR = cvQueryFrame(webcam);

    cvCvtColor(image_opencvBGR,image_opencvRGB,CV_BGR2RGB);
    image = QImage((const unsigned char*)image_opencvRGB->imageData,image_opencvRGB->width,image_opencvRGB->height,QImage::Format_RGB888);
    QRectF target(0.0,0.0,image.width(),image.height());
    QRectF source(0.0,0.0,image.width(),image.height());
    QPainter painter(this);
    painter.drawImage(target,image,source);
}

输出:

收到启动进程信号

但是,当从主图形用户界面(即 MainWindow)发出信号时,除了 Process 插槽外,没有其他插槽在工作。这是由于 movetoThread 命令吗?唐诺,我哪里错了..

最佳答案

答案很简单:Qwidget 不能在主线程之外工作。因此,您不能使用 displaythread 执行 GUI 代码。

此外,您的 while 循环可能会导致问题(我知道该变量是可变的,但我没有时间正确分析它是否正确)

参见 documentation获取更多信息。

ps:看来你做的有点过头了。重新设计你的整个设计。 GUI 操作在主线程中。仅将线程用于计算。如果线程之间的通信和对其变量的访问仅使用信号和槽,则不需要锁定机制。

关于c++ - Qt:信号槽不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13686153/

相关文章:

c++ - bad_alloc 分配数组时

python - 我们可以使用 SWIG 为 Qt 应用程序制作 python 绑定(bind)吗?

python - 缺少 PyQt QML 错误控制台

android - qt qml : deploying sqlite database to android using . qrc 文件不工作

c++ - 如何将 boost::string_view 转换为 std::string_view?

c++ - VC++ Debug模式:批量编辑 std::vector<int> 值?

c++ - 尝试通过引用传递指针时出现此错误

java - 使用 java.util.concurrent API 结束线程

c# - 如何杀死主线程?

java - Java 中的管道或交换输入/输出流