1

我正在尝试在主 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;
}

显示.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);
}

输出 :

接收到的启动过程信号

但是,当从主 gui 即 MainWindow 发出信号时,除了 Process 插槽之外,没有其他插槽正在工作。是由于 movetoThread 命令吗?Donno我哪里错了..

4

1 回答 1

4

答案很简单:Qwidgets 不能在主线程之外工作。所以你不能使用displaythread.

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

有关更多信息,请参阅文档

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

于 2012-12-03T15:32:58.497 回答