Widgets must be created in the GUI thread
-
I have a callback function which runs in another thread. Callback function emits some parameters to GUI thread, when i try to use this parameters for drawing qgraphicsScene, i'm getting these error.
Here's files:
workerthread.h:class workerThread : public QThread { Q_OBJECT public: explicit workerThread(QObject *parent = 0); signals: void sendLocationsFromThread(int, int, int, int); }; extern workerThread *w1; #endif // WORKERTHREAD_H
workerthread.cpp:
workerThread *w1 = new workerThread(); void CallBack(some params) { //this function comes from an external library //some process emit w1->sendLocationsFromThread(x, y, w, h); } workerThread::workerThread(QObject *parent) : QThread(parent) { //some dll load libraries }
mainwindow.h:
namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); QGraphicsView **graphicsViews; void drawGraphicsView(int, int, int, int, some params) public slots: void onLocationChanged(int, int, int, int); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); bool threadConn = connect(w1, SIGNAL(sendLocationsFromThread(int, int, int, int)), this, SLOT(onLocationChanged(int, int, int, int)), Qt::DirectConnection); w1->start(QThread::HighPriority); } MainWindow::~MainWindow() { delete ui; w1->terminate(); } void MainWindow::onLocationChanged(int x, int y, int w, int h) { // creating some params ( create qgraphicView and its specifications etc) graphicsViews= new QGraphicsView* [5]; for(int i = 0; i < 5; i++) { graphicsViews[i] = new QGraphicsView(ui->someWidget); //error occurs with this line drawGraphicsView(int x, int y, int w, int h, some params); } } void MainWindow::drawNewGraphicsView(int x, int y, int w, int h, some params) { //draw somethings on UI with using these parameters }
Drawing or something else working fine, such as when i try to trigger draw function with a button, it's ok. But when i use onLocationChanged function it gives error that i specified in the title.
I used qDebug to see which function works in which thread. onLocationChanged and CallBack is in the same thread. I supposed onLocationChanged must be in the GUI thread, because it is a SLOT of mainwindow.h
How can i solve this problem? Thanks in advance for any help.
-
Your culprit is Qt::DirectConnection. Why are you passing it as direct connection ? Just remove 5th argument(Qt::DirectConnection) and it should work.
-
@dheerendra Mr. Dheerendra, if i remove the 5th parameter just like you said, onLocationChanged in the MainWindow.cpp is not working, i mean qDebug() s in it's not shown so that means function is not being processing i think.
But when i removed Qt::DirectConnection, its not throw any error.
By the way can you explain why this parameter causes block my program? -
You should never use DirectConnection unless know we know why we are using. Communication between threads should be asynchronous. By default is it QuedConnection between threads. So thread context of signal and slots will be different. If you pass the direct connection, you are telling to execute the slots in worker thread. UI object should be created only in Mainthread. Due to this it gave you error. Why do you want pass BlockedQConnection ? Do you want to wait the worker thread till main thread finishes the job ?
-
@dheerendra No, i want to work them to asynchronously, at the same time. But like i said, without
Qt::BlockingQueuedConnection
inside if the onLocationChanged function is not working.
-
Surprise. If it is working for Qt::BlockedQueuedConnection it should work without that also. if you don't pass 5th param, slot is never called ? or is it called later ?
-
@R_Irudezu said in Widgets must be created in the GUI thread:
Qt::BlockingQueuedConnection
You should use Qt::QueuedConnection
If it does not work then it means that you're blocking the event loop somewhere. -
show us more of your
workerthread.h:
especially your overwritten run function.
You decided to go with deriving QThread instead of the worker approach, so you have to manage the thread-event loop yourself. There's a lot that one can do wrong in that placeAs a reminder, I would really suggest going with the worker object and moveToThread:
https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ -
@J.Hilk nothing more is in workerthread.h but i'm gonna write here workerthread.cpp with more details.
workerthread.cpp:
#include "workerthread.h" #include "mainwindow.h" #include <QtCore> #include <QDebug> void callBack(LibraryConnect *connection, LıbraryStruct *drawStruct, uint32_t drawCount) { // dataType struct is keeps some specifications about locations () if (count> 0) { for (uint32_t i = 0; i < drawCount; i++) { int x = drawStruct[i].Location.x; int y = drawStruct[i].Location.y; int w = drawStruct[i].Location.w; int h = drawStruct[i].Location.h; emit w1->sendFaceLocationsFromThread(x, y, w, h); } } }
that's all, in the constructor i'm just initializing some some library functions with using
GetProcAddress //and MAKEINTRESOURCEA(ordinal_number) int connection_return = LibraryConnect ("192.168... ip", port_number); //if returns 0, callBack function starts running
-
I lost the context of issue. If I remember the issue, if you don’t pass 5th parameter slot is not called. This the issue you have now. I suspect slot may be executed fast and u r not able to see change. Just place few debugs in slot and check whether debugs are coming. Comment everything else in slot.
-
@R_Irudezu
I totaly forgot to answer, I'm sorry.So let me clear something up.
If you pass a connect
Direct Connection
the slot is executed in the emitter's thread, which is not necessarily the receiver's thread.Blocking Queued Connection
the slot is invoked as for the Queued Connection, except the current thread blocks until the slot returns. But using this type to connect objects in the same thread will cause deadlock. So you're doing some kind of threading I guess.Usually, if you make a class that has QThread as base class, you have to overwrite run. run() is the starting point of the thread. After calling start(), the newly created thread calls this function. And only stuff created inside run will actually live in the new thread. However you're calling start and your callback function is part of the new QThread class, so that should work also.
For your case, I would maybe suggest looking intp QtConcurrent, it's a high lvl threading api and accepts function pointers as parameters. Seems suited for your case.