[Solved]How to emit signal in diffrent thread ?
-
Hi,
There is an example how to emit a signal from a thread and to handle it my a slot for another thread at "stackoverflow":http://stackoverflow.com/questions/638251/how-to-emit-cross-thread-signal-in-qt.
Cheers,
Leon -
sorry i didn't explain exactly what i need .
I m developing a program that uses opencv , zbar and pocketsphinx . The goal of program is to run programs via voice or qr code . in this function i will get an image from camera check the command using zbar and then run the appropriate software :
@
void Camera::takeImage()
{
capture = cvCreateCameraCapture(0);IplImage* frame;
this->found=false;
while(this->found==false ){
frame = cvQueryFrame(capture);if(frame){
IplImage* greyImage = cvCreateImage(cvSize(frame->width,frame->height),8,1);
cvCvtColor(frame,greyImage,CV_BGR2GRAY);
const unsigned char * data = (unsigned char )(greyImage->imageData);
ImageScanner monScanner ;
monScanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
Image image(frame->width, frame->height, "GREY", data, frame->widthframe->height);
int n = monScanner.scan(image);for(SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
// do something useful with resultsthis->found=true; QString qr=QString::fromStdString(symbol->get_data()); emit foundQrcode(qr); break; }
image.set_data(NULL, 0);
}
}
cvReleaseCapture(&capture);
}and in the GUI class i used the previous slot to run the command when there's a valid qr code in the image :
#include "gui.h"
GUI::GUI() : QWidget()
{
rec=new Record();
rec->setProcessChannelMode(QProcess::MergedChannels);
//hmm=new QString("/usr/local/share/pocketsphinx/model/hmm/en_US/hub4wsj_sc_8k");
//QString lm("/usr/local/share/pocketsphinx/model/lm/en_US/hub4.5000.DMP");
//dic=new QString("/usr/local/share/pocketsphinx/model/lm/en_US/cmu07a.dic");
//rec1=new decodespeech(new QFile("goforward.raw"),new QString(""),new QString(""),new QString(""));
QString* hmm=new QString("/usr/local/share/pocketsphinx/model/hmm/en_US/hub4wsj_sc_8k");
QString* lm=new QString("/usr/local/share/pocketsphinx/model/lm/en_US/hub4.5000.DMP");
QString* dict=new QString("/usr/local/share/pocketsphinx/model/lm/en_US/cmu07a.dic");
decodespeech *rec1=new decodespeech(new QFile("goforward.raw"),hmm,lm,dict);
this->cam=new Camera();
this->exec=new execute();
record =new QPushButton("Record");
stop =new QPushButton("Stop");
qrcode=new QPushButton("qrcode");
output=new QTextEdit() ;
output->setGeometry(5, 5, 200, 150);
vlayout=new QVBoxLayout;
hlayout=new QHBoxLayout;
layout=new QVBoxLayout;
hlayout->addWidget(record);
hlayout->addWidget(stop);
hlayout->addWidget(qrcode);
vlayout->addLayout(hlayout);
vlayout->addWidget(output);
layout->addLayout(vlayout);
setLayout(layout);
QObject::connect(record,SIGNAL(clicked()),rec,SLOT(startRecord()));
QObject::connect(stop,SIGNAL(clicked()),rec,SLOT(stop()));
QObject::connect(qrcode,SIGNAL(clicked()),cam,SLOT(takeImage()));
QObject::connect(cam,SIGNAL(foundQrcode(QString )),output,SLOT(setText(const QString &)));
QObject::connect(cam,SIGNAL(foundQrcode(QString )),exec,SLOT(runCommand(const QString &)));
QObject::connect(rec,SIGNAL(finished()),rec1,SLOT(start()));
QObject::connect(rec1,SIGNAL(isFinished(QString )),output,SLOT(setText(const QString &)));
QObject::connect(rec,SIGNAL(readyReadStandardOutput()),this,SLOT(readoutput()));
QObject::connect(rec,SIGNAL(readyReadStandardError()),this,SLOT(readoutput()));
QObject::connect(rec,SIGNAL(readyReadStandardError()),this,SLOT(error()));
}void GUI::readoutput()
{output->setText(rec->readAllStandardOutput());
}
void GUI::started()
{output->setText("Starting recording...");
}
void GUI::error()
{output->setText(rec->readAllStandardOutput());
}
@
here is the important line :@
QObject::connect(cam,SIGNAL(foundQrcode(QString )),exec,SLOT(runCommand(const QString &)));
@the problem is if i use the qr code button for the first time and the program is running i can't use it again , it seems that the first slot is holding the camera and didn't exit after emitting the signal , that's why i m thinking of running it in a new thread .
I hope i made it clear now .[EDIT: code formatting, please wrap all code in @-tags, Volker]
-
Use emit as always, there is no change when fired in a thread. Use "queued connections":http://doc.qt.nokia.com/latest/qt.html#ConnectionType-enum for the signal-slot connection.
Be aware of the thread affinity of your QObjects in the thread. Please read "Peppe's":http://developer.qt.nokia.com/member/5319 excellent wiki article on "Threads, Events and QObjects":http://developer.qt.nokia.com/wiki/Threads_Events_QObjects to learn the gory details.
Also, put some qDebug() statements into your code, to see where the flow of control hangs or use the debugger to step through.
As your exec object and runCommand method is not provided, it's unclear what is going on there.
-
OK , these are the exec and runCommand
exec :
@#include "execute.h"
//#include <QGeexecute::execute()
{
map.insert("open media","/usr/bin/vlc");
map.insert("close media","pkill vlc");
map.insert("open radio","/usr/bin/vlc");
map.insert("close radio","pkill vlc");}
bool execute::addCommand(const QString cmd,const QString app)
{
if(!map.contains(cmd)){
map.insert(cmd,app);
return true;
}
else return false;
}
bool execute::removeCommand(const QString cmd)
{
int pos=map.remove(cmd);
if(pos>0)
return true;
else return false;
}
void execute::runCommand(const QString str)
{
// QHash<QString,QString>::const_iterator i=map.find(str);
if(map.contains(str)){this->process = new Record(); //this->process->setCommand(map[str]); //qDebug() << this->process->getCommand(); this->process->start(map[str]); if (this->process->waitForStarted()){ emit finished(); } else emit error("enanble to run command"); //return true; } else { emit error("command not found"); }
}
void execute::close()
{
this->process->close();
}
@ -
I found the problem but couldn't fix it . It's in this function :
@void Camera::takeImage()
{
CvCapture* capture = cvCreateCameraCapture(0);qDebug() << "i m here1";
IplImage* frame;
this->found=false;
qDebug() << "i m here2";while(this->found==false ){
frame = cvQueryFrame(capture);qDebug() << "i m here3";
/* here where the function will freeze the second time i use it */
if(frame){qDebug() << "i m here4";/* image=new QImage(); image=this->IplImage2QImage(frame); image->save("snaphot.jpg");*/
IplImage* greyImage = cvCreateImage(cvSize(frame->width,frame->height),8,1);
cvCvtColor(frame,greyImage,CV_BGR2GRAY);
const unsigned char * data = (unsigned char )(greyImage->imageData);
ImageScanner monScanner ;
monScanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
Image image(frame->width, frame->height, "GREY", data, frame->widthframe->height);
int n = monScanner.scan(image);
qDebug() << "i m here5";for(SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
// do something useful with results
cout << "decoded " << symbol->get_type_name() << " symbol "" << symbol->get_data() << '"' << endl;
this->found=true;
QString qr=QString::fromStdString(symbol->get_data());
emit foundQrcode(qr);
break;
qDebug() << "i m here6";}//end for
qDebug() << "i m here7";
}
}
//}while(!frame);
//qDebug() << "sdfsd";cvReleaseCapture(&capture);
qDebug() << "i m here8";}@
when i first use it it works fine but when i use it again it will freeze before the "if(frame)" and the camera won't open .