[solved] Abstract Class -> ASSERT failure in QWidget: "Widgets must be created in the GUI thread
Hi to everyone!
I'm developing with Qt 5.1 (VS2012 - 32bit).
I have a strange problem. I use a abstract class (iLog) and derived classes (e.g. ConsoleLog -> to log into stdout/stderr). One (PopupLog) class creates QMessageBoxes for errors-logs ..
When I use:
Popuplog *p = new Popuplog();
p->error("blah blah");//this is a virtual function -> virtual void iLog::error(QString&) = 0;
It works fine!!
When I use:
iLog *p = new Popuplog();
My software crashes with:
ASSERT failure in QWidget: "Widgets must be created in the GUI thread.", file kernel\qwidget.cpp, line 1111
QObject::killTimers: timers cannot be stopped from another thread
To be honest, I have no clue why!
Do you have any advice or a idea??
best regards Leocor
It depends on whether you are using this class outside the GUI thread, which is the one started by QApplication::exec();
If you need to show a widget from another thread you would need to emit a signal from you thread to the GUI thread and then show the message boxes from there.
Hope it helps
Ok, but I dont know where I start a different Thread!
in my main (slightly different names): (ListLog ConsoleLog & PopupLog are iLog-classes) -> all iLogs have virtual error-functions
QApplication a(argc, argv);
ListLog *logger = new ListLog();
(I also tried to put the log objects in the MainWindow Class .. nothing worked)
Are the Log-objects in a different thread than my MainWindow??
Popuplog creates a 300x100 frameless QMainWindow (nothing more) (prevously it was a QMessageBox ...but it was the same error .. so I tried the QMainWIndow)
I create a popup with:
Popupwin *win = new popupwin();
all the communication to this window is realised over signals/slots
does a QMainWindow and QMessageBox create a new thread?
QMessageBox start's a new event loop but I don't think that's the problem.
What are ListLog, consolelog, and popuplog ?
all these classes are classes to do logging and derive the ilog class.
Loglist is a iLog which calls the logging-functions of all added (in a QList) iLog-objects (so I can log parallel on different outputs)
consolelog ... writes log-entries to stdout & stderr. (I'm just calling std::cout & std::cerr)
well, popuplog .. as i already explained ... creates popups (QMainWindow- object in that case) with logging messages (which disappear after a time-period)
popuplog has a qlist with pointers of (derived) QMainWindow [for the popups] which displays a text. When I call the overwritten function [virtual void] error( QString ) -> it creates a QMainWindow and when the timer (within in the qmainwindow) runs out ...it emits a signal to delete and to remove it from the qList. Thats all for the class ... it's very simpl! Thats the reason why I don't know how this object is in a different thread! ...and when I call the virtual function (error) ... via a popuplog-pointer .. it works fine ... but when I call this function via a iLog-pointer -> it doesn't work!
BTW thx for the fast reply
QMainWindow and QMessageBox do not create new threads.
Do you use QThread, QRunnable or QtConcurrent?
I used a NetLog -> threaded QTcpServer/Sockets (where I used QThread) ... during I searched why this error happens, I removed it -> It doesn't change anything (at the moment this threaded Server is not used) ...
I'm using within my MainProgramWindow[see my second post] (not the popup) a audio-class which creates/modify/converts audio data (Audio-objects are created when i push a button in my MainProgramWindow) ...this audio object generates (during runtime) a derived QThread which works on the audio-data and after it finishes, it gets deleted. But this is within the MainProgrammWindow and my popuplog already exists, when this thread could be created/started.
First of all, thx for your help.
I found my mistake. (actually, it was a rookie-mistake) I have overseen that the objects get moved into a thread when a function gets called.
There were just two lines which causes this trouble. Consequently I created signals and .. now it works. Now its obvious,
Glad to hear that you've resolved it!
[quote author="Leocor" date="1375518333"]I have overseen that the objects get moved into a thread when a function of this object gets called.[/quote]I'm curious about what you mean here?
QObjects "live" in the thread that created them. Unless you explicitly move them using QObject::moveToThread(), they won't move themselves. However, when a member function is called directly, the function will run in the calling thread, regardless of where the QObject lives. That's why signal/slots are the preferred way to pass info between threads.
You might be interested in reading the "QThread documentation":http://qt-project.org/doc/qt-5.1/qtcore/qthread.html and some details on "how QObjects interact with threads":http://qt-project.org/doc/qt-5.1/qtcore/threads-qobject.html.
[quote author="Leocor" date="1375516900"]this audio object generates (during runtime) a derived QThread which works on the audio-data and after it finishes, it gets deleted.[/quote]Make sure you don't add any slots to your derived QThread. That often leads to trouble.
yes you are totaly right! .. sry I wrote it ambiguous!
I meant that, when I call a function, the function gets executed in the thread which called the function. All objects (which get created within this function) are moved to the current thread (which called the function).. More correctly (as you wrote) the function is executed in the thread and, consequently, the objects are created within the thread and stay there.
Sry .. English is a foreign language for me and sometimes my english sounds more correctly in my head than it actually is.
Again, thx JKSH and SGalst