[SOLVED] QT MainWindow freezes when closing OpenCV Webcam Window - new QT Window outside MainWindow
-
That's exactly why I suggested the mandelbrot example, you have there an example of how to implement an forever loop and interact with your application.
You can't update GUI elements from outside the main thread.
Could you post a link to the sdk ?
-
Here are the links:
http://codelaboratories.com/research/view/cl-eye-platform-cpp-sample
http://codelaboratories.com/get/cl-eye-sdk/
the window now closes (typing mistake) correctly. (yeij)
so now if i do this:
@CameraWindow::CameraWindow(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
imageLabel = new QLabel(this);
imageLabel->setTextFormat(Qt::RichText);
imageLabel->setText("textest");
}CameraWindow::~CameraWindow()
{}
@and create a window within my capture class this opens correctly and text is displayed. but if i try to make this a function
@CameraWindow::CameraWindow(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
imageLabel = new QLabel(this);
}CameraWindow::~CameraWindow()
{}
void CameraWindow::dispText(){
imageLabel->setTextFormat(Qt::RichText);
imageLabel->setText("textest");
}@and call camerawindow->dispText() from my capture class i get a "Cannot create children for a parent that is in a different thread" which is akward because obviously imageLabel should be an instance within my CameraWindow not anything else. as CameraWindow is created within this class i really wonder what's going on :)
To your remark: Even if i create a dialog within another thread (obviously another thread because it says so) the GUI Element QLabel i create within this new dialog can only be updated in my MainWindow thread?
If I understand you pointing to the mandelbrot example the solution would be to exchange the orignal sdk thread:
@HANDLE _hThread@
@_hThread = CreateThread(NULL, 0, &CLEyeCameraCapture::CaptureThread, this, 0, 0);@
with another QT Thread creation...
@
RenderThread::RenderThread(QObject *parent)
: QThread(parent)@
which is kind of what i do not feel capable of :)
-
Creating widgets outside the main thread is also forbidden.
Here is a rough idea on how to use a subclassed QThread to get the data from the camera and send them to your widget. (Just the run function actually but it's the most important)
@
void MyQThread::run()
int w, h;
IplImage *pCapImage;
PBYTE pCapBuffer = NULL;// Create camera instance _cam = CLEyeCreateCamera(_cameraGUID, _mode, _resolution, _fps); if(_cam == NULL) return; // Get camera frame dimensions CLEyeCameraGetFrameDimensions(_cam, w, h);
// Depending on color mode chosen, create the appropriate OpenCV image
if(_mode == CLEYE_COLOR)
pCapImage = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 4);
else
pCapImage = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);// Set some camera parameters CLEyeSetCameraParameter(_cam, CLEYE_GAIN, 20); CLEyeSetCameraParameter(_cam, CLEYE_EXPOSURE, 511); CLEyeSetCameraParameter(_cam, CLEYE_ZOOM, (int)(GetRandomNormalized()*100.0)); CLEyeSetCameraParameter(_cam, CLEYE_ROTATION, (int)(GetRandomNormalized()*300.0)); // Start capturing CLEyeCameraStart(_cam); // image capturing loop while(_running) { cvGetImageRawData(pCapImage, &pCapBuffer); CLEyeCameraGetFrame(_cam, pCapBuffer); emit capturedImage(IplImage2QImage(pCapImage)); } // Stop camera capture CLEyeCameraStop(_cam); // Destroy camera object CLEyeDestroyCamera(_cam); _cam = NULL; }
@
Depending on the image format you could even directly capture to a QImage avoiding the conversion.
Hope it helps
-
I followed the mandelbrot example and did alike with my class.
Now, I am not able to acces wait(), start(), isRunning() or any other static (protected?) function which seems either not to be declared or not found.
I included the following, something's missing ?
@
#include <QCoreApplication>
#include <QThread>
#include <QObject>
#include <QMutex>
#include <QWaitCondition>
@ok...it seems that this is because i create a dialog window within the render thread that seems not to be able to parent correctly.
i guess the way would be to open the camerwindow dialog within the mainwindow class and connect the signal of the renderthread to the camerwindow ?
-
Did you subclass QThread and use the code in the run function ?
No widget stuff whatsoever in another thread than the GUI thread (they mean it)
That would be one way yes
-
Ok, seems that something is wrong with the connection:
@1>.\camerawindow.cpp(14) : error C2664: 'bool QObject::connect(const QObject *,const char *,const QObject *,const char *,Qt::ConnectionType)': Konvertierung des Parameters 1 von 'RenderThread **' in 'const QObject *' nicht möglich
1> Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.@although i defined RenderThread as in the example..
@class RenderThread : public QThread
{
Q_OBJECT
@ -
it seems that you are giving the address of the pointer to your RenderThread.
Do you have something like that :
@RenderThread *renderThread = new RenderThread;
conncet(&renderThread, etc....)@?
-
The best is to go one step at a time, first get the data from the camera, then add the widget etc... Trying to make all at the same time is recipe for failure
-
going with your version didn't work out so i went with this:
camerawindow.cpp:
@CameraWindow::CameraWindow(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
QLabel *imageLabel = new QLabel(this);qRegisterMetaType<QImage>("QImage");
connect(&thread, SIGNAL(renderedImage(QImage)),
this, SLOT(updatePixmap(QImage)));setWindowTitle(tr("multithread"));
}...
int CameraWindow::startCaptureThread(){
this->show();RenderThread *thread = new RenderThread(this, windowName, guid, CLEYE_COLOR_RAW, CLEYE_VGA, 50);
thread->StartCapture("abc");
}
@which seems to work fine as looping the run() while loop correctly,
but obviously the updatePixmap function is never called so the objects might be mislinked or created in wrong syntax... frustrating ;)
-
i tried with another connection:
@ connect(&thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));@@void CameraWindow::debugSomething(std::string something){
QString somethings(something.c_str());
qDebug()<<somethings;
}@renderthread.cpp:
@while(_running)
{
emit sendText(text);
}@and this as well seems not to emit anything or not correctly connect to the qdialog. why is this not working as it should ?
-
You should replace all std::string with QString, that will avoid you some problems.
Your while loop might be a bit short and might block the main thread.If your code is not top secret, could you share it i.e. via gitorious/github/other vcs service ? That might make things easier to look at
-
Hi SGaist,
after getting a bit tired refitting the Mandelbrot Example to my needs I asked this question at StackOverflow. It turns out that there are some issues the way the example uses threads. I don't know if I could have saved my code but I was getting depressed so I recoded the way somebody pointed me out at StackOverflow and this worked instantly and also avoids image conversion as i can use the opencv namendWindow.
@//create new thread
QThread* thread = new QThread;//init camera with guid, raw color capture, vga format and 50fps
cameraCapture = new CLEyeCameraCapture(winName, folder, userID, guid, CLEYE_COLOR_RAW, CLEYE_VGA, 50);
cameraCapture->moveToThread(thread);connect(thread, SIGNAL(started()), cameraCapture, SLOT(StartCapture()));
connect(cameraCapture, SIGNAL(finished()), thread, SLOT(quit()));
connect(cameraCapture, SIGNAL(finished()), cameraCapture, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
connect(ui.pushButton_startLogging, SIGNAL ( clicked() ),this,SLOT( activateLogging() ) );
connect(ui.pushButton_stopLogging, SIGNAL ( clicked() ),this,SLOT( deactivateLogging() ) );
@I tried to follow this "example.":http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
Here is the "Question on SO.":http://stackoverflow.com/questions/18594528/create-thread-in-qdialog-and-emit-signals-to-qdialog-in-qt
Thank you for your help. Now i avoided the freezes. It might be of interest for people who using any conversion from IplImage to QImage: non of the conversions are fast enough for realtime (I did not measure wether the conversion or the displaying method is slowing down the process).
Thank you anyway for your help. I guess it is wise for anybody who rebuilds this to use their original code and put it in a Worker which then gets moved to a QThread.