Qt:信号插槽不工作

时间:2012-12-03 15:17:07

标签: c++ multithreading qt qthread qt-signals

我正在尝试在主gui和另一个移动到另一个线程的对象之间实现Signal和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 class 的指针,看起来像

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);
}

输出:

收到的启动过程信号

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

1 个答案:

答案 0 :(得分:4)

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

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

有关详细信息,请参阅documentation

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