1

メインのGUIと別のスレッドに移動された別のオブジェクトの間にSignalandSlotシステムを実装しようとしています...クラスデザインは次のようになります...残念ながら実装できません...

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コマンドによるものですか。私が間違っているところのドンノ..

4

1 に答える 1

4

答えは簡単です。Qwidgetsはメインスレッドの外では機能しません。したがって、を使用してGUIコードを実行することはできませんdisplaythread

さらに、whileループが問題を引き起こす可能性があります(変数が揮発性であることはわかっていますが、正しいかどうかを適切に分析する時間がありません)

詳細については、ドキュメントを参照してください。

ps:あなたは物事をやり過ぎているようです。デザイン全体を作り直します。GUI操作はメインスレッドにあります。スレッドは計算にのみ使用してください。スレッドとそれらの変数へのアクセスの間の通信が信号とスロットのみを使用する場合、ロックメカニズムは必要ありません。

于 2012-12-03T15:32:58.497 に答える