I'm creating a Qt GUI that will generate some forms for the user, let them fill them in, and then save the forms in a binary search tree that will then be serialized. This is done using Qt (obviously), c++, and boost. The GUI is the only interface with the application at this point. I would like to instantiate my binary search tree object outside of the GUI as creating it inside the main GUI class seems to be a bad design pattern. Is this thought correct?
Here's my main() right now:
int main (int argc, char *argv[])
{
QApplication app(argc, argv);
ChocAnGui *gui = new ChocAnGui;
gui->show();
return app.exec();
}
Is there a way to create a BST object that the ChocAnGui class can use, but that lives outside of the actual GUI? I'd like to do something like:
int main (int argc, char *argv[])
{
MyBST bst = new MyBST;
MyRecord record = new MyRecord;
QApplication app(argc, argv);
ChocAnGui *gui = new ChocAnGui;
gui->show();
return app.exec();
}
I would then like the GUI to be able to call methods on the MyBST and MyRecord classes from within. Because at the start and finish of the application I am serializing and de-serializing data, this seems to be the most abstract approach (vs. serializing and de-serializing from within the GUI code itself). I hope this question is clear... I'm learning all this stuff as we speak. Is there a way to pass those vars through QApplication(argc, argv)? Eventually the record and BST classes will be built into a database and, again, creating the instances outside of the GUI seems most straightforward. Thanks for any input you can provide.
I think it is necessary for you to put your binary search tree outside the GUI thread only when your Binary search takes a long time and is possible to block the GUI's thread.
If this is the case, the what you wanna do is to put the MyBST object under another thread,
In your main application, create a new thread that will handle all BST operations:
QThread * BSTThread = new QThread();
BSTThread->start();
BSTThread is a new thread that has its own event queue.
Then you create you MyBST Object, Make sure MyBST inherits QObject, and you can call the moveToThread method on the object.
MyBST * bst = new MyBST();
bst->moveToThread(BSTThread);
When the main application wants to communicate with the MyBST, you emit a signal from you main application. Connect the signal to a slot in the MyBST class using Qt::QueuedConnection, or just use Qt::AutoConnection, it will automatically be queuedconnection because your bst object lives in a different thread as the main app, and the function in the slot will be executed by the BSTThread.
And when the bst object wants to communicate back to the main app, also emit a signal, this signal is connected to the slot in the main app, which will handle this properly in your mainThread. In this way, your communication is asynchronous, you can not get the result immediately when you send request to the bst object, because you send it as a signal and it is posted in the event queue of the BSTThread waiting to be processed. After the BSTThread processed the request from the main app, it posts back the result to the main thread's event queue, the main thread handles the results and updates the GUI.
I think you need to read this http://doc.qt.digia.com/qt/thread-basics.html on QT if you want to know more details.
Just create your window to declare a MyBST member:
class MyBST;
class ChocAnGui
: public QMainWindow
{
Q_OBJECT
public:
ChocAnGui(MyBST* aBst = 0, QWidget *parent = 0);
MyBST *bst
And then initialize it with your object:
ChocAnGui *gui = new ChocAnGui(bst);
Or you can not make it a member, and make your gui just always take a MyBST pointer:
class MyBST;
class ChocAnGui
: public QMainWindow
{
Q_OBJECT
public:
ChocAnGui(QWidget *parent = 0);
void doSomething(MyBST*);
Related
I am learning QT and am trying to get my signals and slots working. I am having no luck.
Here is my Main
int main(int argc, char** argv) {
QApplication app(argc, argv);
FilmInput fi;
FilmWriter fw;
QObject::connect (&fi->okButton, SIGNAL( clicked() ), &fi, SLOT( okButtonClicked() )
); //Error received Base operand of '->' has non-pointer type 'FilmInput'
QObject::connect(&fi,SIGNAL(obtainFilmData(QVariant*)),&fw,SLOT(saveFilmData(QVariant*)));
//Error received No matching function for call to 'QObject::connect(Filminput*, const char*, FilmWriter*, const char*)
fi.show();
return app.exec();
}
and here is my sad attempt at signals and slots:
FilmInput.h
public:
FilmInput();
void okButtonClicked();
QPushButton* okButton;
signals:
void obtainFilmData(Film *film);
Here is FilmWriter.h
public slots:
int saveFilm(Film &f);
Here is Film Input.cpp
void FilmInput::okButtonClicked(){
Film *aFilm=new Film();
aFilm->setDirector(this->edtDirector->text());
emit obtainFilmData(aFilm);
}
Here is FilmWriter.cpp
void FilmInput::okButtonClicked(){
Film *aFilm=new Film();
aFilm->setDirector(this->edtDirector->text());
emit obtainFilmData(aFilm);
}
Please assist me in getting the signals and slots to work, I have spent hours but am no closer to getting it working. I have added the errors received in my comments above.
Regards
okButton is already a pointer, then you should remove the ampersand:
QObject::connect(fi.okButton, SIGNAL(clicked()), &fi, SLOT(okButtonClicked()));
(actually, be sure you create the button in FilmInput' constructor...)
Next, your methods signature doesn't match what you say in connect: given your functions, should be
Object::connect(&fi, SIGNAL(obtainFilmData(Film*)), &fw, SLOT(saveFilmData(Film*)));
this will work, because you are exchanging a pointer, and then Qt can make a copy of it. Otherwise, your type should be registered.
The first error is caused by &fi->okButton because -> has a higher precedence than &. See Operator Precedence. Easily fixed with (&fi)->okButton.
The second error is likely caused by one or both objects not inheriting from QObject. Signals and slots can only work between QObjects. Just a quick checklist:
Both sender and receiver must inherit from the QObject class
The Q_OBJECT macro must be used in the definition of each class
You must generate the appropriate meta-object code and compile it into your project. See Meta-Object Compiler
Also, if you're using Qt version 5.0 or higher, you should start passing function pointers to the connect methods instead of using the SIGNAL and SLOT macros. It'll provide compile-time checking of the connections.
I'm new to Qt, and want to simply display a video in Qt GUI. I basically got everything figured out, except for some details handling the QThread, which is really annoying.
I reformulate my question into a simpler program, hope it will explains better
first I define this QObject class
#include <QObject>
#include <QDebug>
class myObject : public QObject
{
Q_OBJECT
public:
explicit myObject(QObject *parent = 0);
bool stop;
signals:
void finishWork();
public slots:
void dowork();
void onfinishThread();
};
myObject::myObject(QObject *parent) :
QObject(parent)
{
stop = true;
}
void myObject::dowork(){
qDebug()<<"start working!";
while(!stop){
qDebug()<<"working...";
}
emit finishWork();
qDebug()<<"finish do work!";
}
void myObject::onfinishThread(){
qDebug()<<"thread is finished!";
}
then the main function
#include <QCoreApplication>
#include <QThread>
#include <iostream>
#include <windows.h>
#include "myobject.h"
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
myObject* myObj = new myObject();
QThread* myThread = new QThread;
myThread->connect(myObj, SIGNAL(finishWork()), SLOT(quit()));
myObj->connect(myThread, SIGNAL(started()), SLOT(dowork()));
myObj->connect(myThread, SIGNAL(finished()), SLOT(onfinishThread()));
myObj->moveToThread(myThread);
myObj->stop = false;
myThread->start();
cout<<"Press ENTER to continue....."<<endl<<endl;
cin.ignore(1);
myObj->stop = true;
Sleep(10);
if(myThread->isRunning()){
qDebug()<<"The thread is still running?!!!";
}
/*
myObj->stop = false;
Sleep(1000);
myThread->start();
myObj->stop = true;
*/
myObj->deleteLater();
myThread->deleteLater();
return a.exec();
}
As you can see, I even used cin to try let the dowork() run first, but it didn't work at all, the output is
so I'm really confused on how scheduling works for QThread...
Also, if you uncomment the part
/*
myObj->stop = false;
Sleep(1000);
myThread->start();
myObj->stop = true;
*/
the output is exactly the same! only stays a while after printing
The thread is still running?!!!
Would anyone help me with this? Thanks a lot. You may simply copy all the code and test it yourself.
-------------------------Original Question, bad explanation, please ignore....----------------------------------------
I made a videoObj Class with only one function to Query the frames, the function is defined as:
void videoObj::ProcessFrame(){
bool getframe;
qDebug()<<"get in ProcessFrame";
while(!stop_flag){
getframe = capture_.read(imgOriginal_);
if(!getframe){
qDebug()<<"Video End!";
break;
}
cv::cvtColor(imgOriginal_, imgOriginal_, CV_BGR2RGB);
QImage qimgOriginal((uchar*)imgOriginal_.data, imgOriginal_.cols, imgOriginal_.rows, imgOriginal_.step, QImage::Format_RGB888);
emit imgProcessed(qimgOriginal);
this->thread()->msleep(10);
//qDebug()<<"processing frames";
}
emit stopProcess();
qDebug()<<"Stop thread";
}
Basically above code is just query frames and whenever got one emit the
SIGNAL imgProcessed(qimgOriginal)
and whenever the stop_flag is set on, stop the while loop and emit the
SIGNAL stopProcess()
I use this class in the MainWindow Class, here is how I define the connection in the constructor:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
video_obj_ = new videoObj();
video_thread_ = new QThread;
this->connect(video_obj_, SIGNAL(imgProcessed(QImage)), SLOT(onImgProcssed(QImage))); \\this is for displaying the image
video_obj_->connect(video_thread_, SIGNAL(started()), SLOT(ProcessFrame()));
video_obj_->moveToThread(video_thread_);
video_thread_->connect(video_obj_, SIGNAL(stopProcess()), SLOT(quit()));
}
Above code works fine in frame query. The problem I don't understand is, if I set video_obj_->stop_flag on in any MainWiow member function, the ProcessFrame() in videoObj Class should emit stopProcess() signal and trigger quit() of video_thread_, and then the thread should finish, that is video_thread_->finished() is true.
However, if I do something like:
connect(video_thread_, SIGNAL(finished()), this, SLOT(onStopProcess())); //onStopProcess() see below
void MainWindow::on_btnStart_clicked()
{
video_obj_->stop_flag = 1;
this->thread()->msleep(10);
video_obj_->capture_.open(ui->lineEditVidoeAddress->text().toStdString());
//... something about videoCapture setting here, not related
video_obj_->capture_.set(CV_CAP_PROP_POS_FRAMES, 0);
video_obj_->stop_flag = 0;
this->thread()->msleep(10);
if(video_thread_->isRunning()){
qDebug()<<"The thread is still running?!!!";
}
video_thread_->start();
}
void MainWindow::onStopProcess(){
qDebug()<<"thread is finished";
}
It will give me the output:
Stop thread
The thread is still running?!!!
thread is finished
Which means triggering the quit() is not finish the thread, or quit() has not been triggered.
If I use:
video_thread_->wait(); //instead of video_thread_->wait(10);
The program will just freeze.
Is anyone can help me with this, it really confuse me about this quit() and finished()...
Thanks!
Since when you call stop_flag=1, the video_thread_ finishes the current function which is
ProcessFrame
before ProcessFrame finish, quit is called on the video_thread_ through emit stopProcess().
However, quit is different from terminate, terminate can exit the thread any time (but it is not safe), quit works with the event loop, if the thread has no eventloop, quit has no effect.
I guess before qthread execute the next event in the eventloop, it checks some flag, which can be set by quit, it the flag is set by quit, then it won't execute the next event in the eventloop. Or it can also be that a quit event is inserted into the eventloop, and the next event in the eventloop will be quit.
After stop_flag = 1, you called video_thread_->wait, that will block the video_thread_ from executing the next event in the eventloop, thus the quit will not take effect before time out, however, the nextlines which print "not finished?!!!" is executed immediately. Instead of calling video_thread->wait, if you call currentThread()->Sleep(some_enough_time), then there will be time for the video_thread_ to execute the next event and quit.
You can read the Qt documentation of QThread, wait is used with terminate to terminate a thread synchronously.
============================== The new code ================================
When you do:
myObj->connect(myThread, SIGNAL(started()), SLOT(dowork()));
The signal source is myThread, the slot also belongs to myThread, since the object "myThread" is created in the main thread, thus as a object it lives in the main thread. You can call myThread->thread() to see this, it will return the main thread instead of the new thread.
However, the started signal is emitted from the new thread namely the thread that myThread represents, thus the connection is a Qt::QueuedConnection. dowork() is posted in the event queue of main thread, and it'll be executed only after a.exec() which executes the main threads eventloop.
The same thing happens to the other 2 connect calls, all the slots will be executed in the eventloop of the main thread.
First the start is emitted from the new thread when myThread->start is called, dowork is posted in the main thread's event queue.
Nothing really happens before you call a.exec();
So the program will go ahead to cin and then set stop to true, and then print "Thread is still running?!!".
Second When a.exec() is called, the dowork is executed in the main thread and "start work" is printed. Nothing is done because the stop flag is already true, and the finishwork signal is emitted from the main thread, print "finish do work";
Third The last step the finishwork is emitted, and the quit slot is directly called. However, before the new thread can really quit, the main thread has already finished the eventqueue, because no more events are posted to the main thread. The application exits without waiting for quit() to take effect.
To test this is true, do not modify any of your code, just add after
emit finishWork();
currentThread()->sleep(1000);
you will see "thread is finished!" printed, because this make time for the new thread to emit finished(), and the onfinishThread() will be add to the main thread's eventqueue.
BTW, your way of working with thread looks like java style, which is not the standard qt way. You can read this before you work on qt thread.
This is not a scheduling issue.
That you did in your code looks like:
Create a thread.
Then this thread emits a signal that it started, run slot dowork()
start a thread.
Wait for user input
echo about thread is running
execute event loop
At point 3 thread is already running and signalled about that. Because myObj is created in main thread and not moved to any other thread (to process events there), your thread does not do anything else now, but just spins event loop. At the same time event that tells you want to run myObj's dowork() is posted on the main thread. At last then it comes to step 6 you start to execute event loop of it, and first thing it finds is event that it needs to call dowork() on myObj.
To make it clear to you how Qt threads and signal-slot connection works, I recommend you to read this article on Qt blog.
In simple to fix it, you can move your object myObj to the thread that you wan't to run.
But to make this really correct, I bet that you really want is to subclass QRunnable and (re-)implement it's run method to do the stuff you wan't in QThread, so that thread does it's job, than finished correctly, so you can join on it. Or depending on your goal you might be even better with using QtConcurrent::run(aFunction)
I am having some difficulty fully grasping how signals and slots are used in Qt. I am sure it is really basic but I'm just no getting it today.
I have a set of widgets a bit like this:
MainWindow
-->StackedWidget
-->ChildForms
Now the idea is that there are some actions on the Child widgets that will cause the stacked widget to display a different page.
So if I understand it properly I thought the way to connect signals and slots is to use the connect() at the scope that knows about the objects but what I have managed to get working doesn't do it this way. At the moment in my child form I use parentWidget() to access the slot of the StackedWidget but I am not very happy with really because it is giving the child information about the parent which it shouldn't have:
void TaskSelectionForm::setButtonMappings()
{
// Set up a mapping between the buttons and the pages
QSignalMapper *mapper = new QSignalMapper(this);
connect(mapper, SIGNAL(mapped(int)), parentWidget(), SLOT(setCurrentIndex(int)));
mapper->setMapping(ui->utilitiesButton, 2); // Value of the index
connect(ui->utilitiesButton, SIGNAL(clicked()), mapper, SLOT(map()));
}
But I am not really sure how I should do this and connect it up. Do I need to have signals at each level and emit through the tree?
A Bit of Signal-Slot Theory
The signal-slot connections are oblivious to parent-child relationships between QObjects, and any such relationship doesn't matter. You're free to connect objects to their children, to their siblings, to their parents, or even to QObjects that are in a separate hierarchy, or to lone QObjects that have neither parents nor children. It doesn't matter.
A signal-slot connection connects a signal on a particular instance of QObject to slot on another instance of QObject. To use the connect method, you need the pointers to the instance of sender QObject and the instance of receiver QObject. You then use the static QObject::connect(sender, SIGNAL(...), receiver, SLOT(...)). Those connections have nothing to do with any hierarchy there is between the sender and receiver.
You can also connect a signal to a signal, to forward it -- for example from a private UI element to a signal that's part of the API of the class. You cannot connect a slot to a slot, because it'd incur a bit of runtime overhead for a rarely-used case. The overhead would be an extra bool member in QObjectPrivate, plus a failed if (bool) test. If you want to forward slots to slots, there are at least two ways to do it:
Emit a signal in the source slot and connect that signal to the destination slot.
Obtain a list of all signals connected to the source slot, iterate on it and connect them to to the target slot. There's no easy way to maintain such connections when further signals are connected or disconnected from the source slot. Unfortunately, QObject only has a connectNotify(const char*) protected function, but not a signal -- so you can't hook up to it unless you would modify src/corelib/kernel/qobject[.cpp,_p.h,.h] to emit such a signal. If you truly need it, just modify the Qt source, you have access it for a reason, after all. Hacking the vtable without modifying Qt is possible, but discouraged for obvious reasons.
The Answer
Below is a self contained example that shows how to do what you want. Turns out I have answers to quite a few questions from my various experiments I've done in Qt in the past. I'm a packrat when it comes to test code. It's all SSCCE to boot :)
// https://github.com/KubaO/stackoverflown/tree/master/questions/signal-slot-hierarchy-10783656
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
class Window : public QWidget
{
QSignalMapper m_mapper;
QStackedLayout m_stack{this};
QWidget m_page1, m_page2;
QHBoxLayout m_layout1{&m_page1}, m_layout2{&m_page2};
QLabel m_label1{"Page 1"}, m_label2{"Page 2"};
QPushButton m_button1{"Show Page 2"}, m_button2{"Show Page 1"};
public:
Window(QWidget * parent = {}) : QWidget(parent) {
// the mapper tells the stack which page to switch to
connect(&m_mapper, SIGNAL(mapped(int)), &m_stack, SLOT(setCurrentIndex(int)));
// Page 1
m_layout1.addWidget(&m_label1);
m_layout1.addWidget(&m_button1);
// tell the mapper to map signals coming from this button to integer 1 (index of page 2)
m_mapper.setMapping(&m_button1, 1);
// when the button is clicked, the mapper will do its mapping and emit the mapped() signal
connect(&m_button1, SIGNAL(clicked()), &m_mapper, SLOT(map()));
m_stack.addWidget(&m_page1);
// Page 2
m_layout2.addWidget(&m_label2);
m_layout2.addWidget(&m_button2);
// tell the mapper to map signals coming from this button to integer 0 (index of page 1)
m_mapper.setMapping(&m_button2, 0);
connect(&m_button2, SIGNAL(clicked()), &m_mapper, SLOT(map()));
m_stack.addWidget(&m_page2);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Window w;
w.show();
return a.exec();
}
Connect(stackedwidget->currentactivewidget,SIGNAL(OnAction()),this,SLOT(PrivateSlot()));
PrivateSlot() is a slot declared privately. So in this function, you can add your code to change the page of stackedwidget corresponding to the action produced by currentactivewidget.
Again if you really want to pass the signal up the heirarchy, emit a publicsignal() at the end of private slot function.
Connect(this,SIGNAL(publicsignal()),Parentwidgetofstackedwidget(here mainwindow),SLOT(mainwindow_slot()));
I have an event filter and I noticed when I click to expand/collapse a tree branch I get QEvent::MetaCall. I was thinking about using this to roll my own expand/collapse code, but I don't know how to get any information, such as the index of the item.
Is there anything available from this MetaCall event type?
I found someone had asked this same question on another site, but without an answer, here:
http://www.qtcentre.org/threads/37525-How-to-filter-QEvent-MetaCall
What is this event typically used for?
The biggest question are: What exactly are you trying to do? What is the Qt class that received those events? As far as I'm concerned, you're trying to do things the hard way, so why bother?
The QMetaCallEvent is the event representing a slot call whenever a queued connection is used to invoke a slot. This might be due to a signal firing that was connected to a slot, or due to the use QMetaObject::invoke or QMetaObject::invokeMethod. The queued connection bit is the important part! Queued connections are not used by default for calls between objects in the same thread, since they have the event queue management overhead, unless either of the two conditions below holds true:
You provide Qt::QueuedConnection argument to QObject::connect or QMetaObject::invoke[Method], or
The receiving object's thread() is different from the thread where the call is originating - at the time of the call.
The QMetaCallEvent event class carries the information needed to invoke a slot. It contains the sender QObject and its signal id (if the call comes from a signal-slot connection), as well as the target slot identifier, and the arguments needed to be passed into the slot.
Thus, you could check if the called slot is the one you wish to intercept, as well as what arguments were passed to it. For example, if you're calling a slot with a single int parameter, then *reinterpret_cast<int*>(metaCallEvent->args()[1]) will give you the value of that integer. The zero-th argument is used for the return value, if any, so the parameters are indexed with base 1.
Disclaimer Since the QMetaCallEvent class is internal to Qt's implementation, you're making your application's binary tied to the particular Qt version in full (entire major.minor version) and you lose the benefits of binary compatibility offered by Qt across the major version. Your code may still compile but cease to work properly when you switch to another minor version of Qt!
The below applies to Qt 5.2.0, I have not looked at any other versions!
So, suppose you want to intercept a call to QLabel::setNum. You'd catch such events as follows:
#include <private/qobject_p.h> // Declaration of QMetaCallEvent
bool Object::eventFilter(QObject * watched, QEvent * event) {
QLabel * label = qobject_cast<QLabel*>(watched);
if (! label || event->type() != QEvent::MetaCall) return false;
QMetaCallEvent * mev = static_cast<QMetaCallEvent*>(event);
static int setNumIdx = QLabel::staticMetaObject.indexOfSlot("setNum(int)");
if (mev->id() != setNumIdx) return false;
int num = *reinterpret_cast<int*>(mev->args()[1]);
// At this point, we can invoke setNum ourselves and discard the event
label->setNum(num);
return true;
}
If you want to see, globally, all slots that are called using the metacall system, you can do that too. Template parametrization of the base class allows flexibility to use any application class - say QCoreApplication, QGuiApplication, QApplication, or a user-derived type.
template <class Base> class MetaCallWatcher : public Base {
MetaCallWatcher(int& argc, char** argv) : Base(argc, argv) {}
bool notify(QObject * receiver, QEvent * event) {
if (event->type() == QEvent::MetaCall) {
QMetaCallEvent * mev = static_cast<QMetaCallEvent*>(event);
QMetaMethod slot = receiver->metaObject()->method(mev->id());
qDebug() << "Metacall:" << receiver << slot.methodSignature();
}
return Base::notify(receiver, event);
}
}
int main(int argc, char ** argv) {
MetaCallWatcher<QApplication> app(argc, argv);
...
}
The QEvent::MetaCall-type event is created whenever a signal has been emitted that is connected to a slot in the receiving QObject. Reacting to this event in a custom filter/event handler seems to circumvent Qt's mightiest feature, the signal-slot architecture. It's probably better to find out which slot is called and if that slot is virtual so you can overload it.
QEvent::MetaCall is used for delivering cross-thread signals.
In short, I get following error:
QObject::connect: Cannot queue arguments of type 'cv::Mat'
(Make sure 'cv::Mat' is registered using qRegisterMetaType().)
What I'm trying to do is send a signal containing two cv::Mat images from a QThread to the main thread, so that I can display the output. There's no compile time error, but when I run the program, it gets stuck at a breakpoint in qglobal.h (inline void qt_noop() {}).
I've tried to add Q_DECLARE_METATYPE(cv::Mat) to the code, to no avail. I'm quite suck with what to do now.
code
In a QThread class:
signals:
void sndFlow(cv::Mat &leftEye, cv::Mat &rightEye);
void eyesDriver::run()
{
forever
{
flow->draw(leftEye, rightEye);
sndFlow(leftEye, rightEye);
}
}
Capturing in a QObject class:
public slots:
void recFlow(cv::Mat &leftEye, cv::Mat &rightEye);
void myClass::recFlow(cv::Mat &leftEye, cv::Mat &rightEye)
{
cv::imshow("left", leftEye);
cv::imshow("rigth", rightEye);
cv::waitKey(40);
}
In main:
Q_DECLARE_METATYPE(cv::Mat)
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType< cv::Mat >("cv::Mat");
// create objects from QThread and QObject class
QObject::connect(&qthread, SIGNAL(sndFlow(cv::Mat&,cv::Mat&)),
&qobject, SLOT(recFlow(cv::Mat&,cv::Mat&)));
qthread.start();
return a.exec();
}
Changing the signal-slot variables to QSharedPointer< cv::Mat > does not work either. Gives the same error:
QObject::connect: Cannot queue arguments of type 'QSharedPointer<cv::Mat>'
(Make sure 'QSharedPointer<cv::Mat>' is registered using qRegisterMetaType().)
WORKS
All right, it seems to work. I've move qRegisterMetaType< cv::Mat >("cv::Mat"); right before the QObject::connect call. However I still have to 'F5' past the breakpoint in qglobal.h, it works afterwards.
I might be wrong, but it seems that the location of qRegisterMetaType is not trivial.
You need to call qRegisterMetaType in addition to the macro (or instead of it, depending on your needs). This is necessary for the signals to be able to marshal your data across threads. However, it might be a wiser idea to pass by reference or smart pointer, or raw pointer if you are using the QObject hierarchy to manage the object lifetime.