Thank you for your quick response. However, as I was concerned that I would, I managed to improperly simplify my code and not show the real problem. Let's try this again, with actual class names that make a bit more sense.
There are three main classes involved here: CameraThread, Controller, and NozzleApp.
The idea behind CameraThread is to keep all of the low-level interaction of the camera out of the main UI class. What it *SHOULD* be doing is every time a timer goes off, expose and transfer a new image. All I want it to do, ultimately, is emit a signal that contains a new image (an OpenCV Mat in this case), and perform all of its tasks in a separate thread. This is seen below:
class CameraThread
: public QObject{
Q_OBJECT
public:
CameraThread();
private:
Camera* camera;
private slots:
void getNewImage();
signals:
void newImage(Mat);
};
CameraThread::CameraThread()
{
camera = new Camera();
QObject::connect(&imageTimer,
SIGNAL(timeout
()),
this,
SLOT(getNewImage
()));
}
void CameraThread::getNewImage()
{
Mat image_out;
camera->captureSingleImage();
image_out = camera->lastImageColor();
emit newImage(image_out);
}
class CameraThread : public QObject
{
Q_OBJECT
public:
CameraThread();
private:
Camera* camera;
QTimer imageTimer;
private slots:
void getNewImage();
signals:
void newImage(Mat);
};
CameraThread::CameraThread()
{
camera = new Camera();
QObject::connect(&imageTimer, SIGNAL(timeout()), this, SLOT(getNewImage()));
}
void CameraThread::getNewImage()
{
Mat image_out;
camera->captureSingleImage();
image_out = camera->lastImageColor();
emit newImage(image_out);
}
To copy to clipboard, switch view to plain text mode
The Controller class is the interface to some heavy-duty image processing routines. It has its own threaded "pipeline" of processing steps, which works great in its own thread (it was created by sub-classing QThread and reimplementing run()). In this case, its only job is to receive any new images, save some state/data about them, and then pass them off to this processing pipeline.
{
Q_OBJECT
public:
Controller(NozzleApp* parent);
private:
NozzleApp* myParent;
private slots:
void handleNewImage(Mat newImage);
signals:
void new_input_image(Mat);
};
Controller::Controller(NozzleApp *parent) : myParent(parent)
{
}
void Controller::handleNewImage(Mat newImage)
{
// save some state first
emit new_input_image(newImage);
}
class Controller : public QObject
{
Q_OBJECT
public:
Controller(NozzleApp* parent);
private:
NozzleApp* myParent;
private slots:
void handleNewImage(Mat newImage);
signals:
void new_input_image(Mat);
};
Controller::Controller(NozzleApp *parent) : myParent(parent)
{
}
void Controller::handleNewImage(Mat newImage)
{
// save some state first
emit new_input_image(newImage);
}
To copy to clipboard, switch view to plain text mode
Finally, NozzleApp is the high-level GUI class. It creates most of the major objects, and sets up some of the communication between objects. Note that the Controller gets passed its parent object (NozzleApp), but CameraThread does not.
{
Q_OBJECT
public:
NozzleApp();
private:
Controller* controller;
CameraThread* cam_thread;
};
NozzleApp::NozzleApp()
{
setupUi(this);
controller = new Controller(this);
cam_thread = new CameraThread();
QObject::connect(cam_thread,
SIGNAL(newImage
(Mat
)), controller,
SLOT(handleNewImage
(Mat
)));
camera_thread.start();
cam_thread->moveToThread(&camera_thread);
}
class NozzleApp : public QMainWindow
{
Q_OBJECT
public:
NozzleApp();
private:
Controller* controller;
CameraThread* cam_thread;
QThread camera_thread;
};
NozzleApp::NozzleApp()
{
setupUi(this);
controller = new Controller(this);
cam_thread = new CameraThread();
QObject::connect(cam_thread, SIGNAL(newImage(Mat)), controller, SLOT(handleNewImage(Mat)));
camera_thread.start();
cam_thread->moveToThread(&camera_thread);
}
To copy to clipboard, switch view to plain text mode
So, back to the original question: What I would hope and expect to see is that the slot getNewImage() in CameraThread (which does the time expensive camera opterations) is executed in a different thread then handleNewImage() in Controller. This is not happening - why?
Based on everything I've read, and based on your prior response, those two slots are NOT in the same context. I realize that I neglected the QTimer of kicking off getNewImage(), but I figured since the QTimer was supposedly in my new thread, well then its slot would also execute in the new thread (which is not the case).
Thanks again,
Barry
Bookmarks