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

MainWindow.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;

MainWindow.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类的指针,看起来像

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;

displaythread.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;

display.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 ..是否是由于movetoThread命令引起的?唐诺我要去哪里错了..

最佳答案

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

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

有关更多信息,请参见documentation

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

09-30 15:32