I am using Qt 4.6.0 (32 bit) under Windows 7 Ultimate. Consider the following QThread
:
Interface
class ResultThread : public QThread
{
Q_OBJECT
QString _post_data;
QNetworkAccessManager _net_acc_mgr;
signals:
void onFinished(QNetworkReply* net_reply);
private slots:
void onReplyFinished(QNetworkReply* net_reply);
public:
ResultThread();
void run();
void setPostData(const QString& post_data);
};
Implementation
ResultThread::ResultThread() : _net_acc_mgr(this)
{
connect(&_net_acc_mgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onReplyFinished(QNetworkReply*)));
}
void ResultThread::onReplyFinished(QNetworkReply* net_reply)
{
emit onFinished(net_reply);
}
void ResultThread::setPostData(const QString& post_data)
{
_post_data = post_data;
}
void ResultThread::run()
{
_net_acc_mgr.post(QNetworkRequest(QUrl("http://[omitted]")),
QByteArray(_post_data.toStdString().c_str()));
}
Whenever _net_acc_mgr.post()
is executed in ResultThread::run()
, I got the following Application Output in Qt Creator:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x22fe58), parent’s thread is QThread(0x9284190), current thread is ResultThread(0x22fe48)
What does this mean? How to solve it?
EDIT:
I tried doing what you guys told me in comments … :
Citizen * c = new Citizen(this);
QThread thread;
c->moveToThread(&thread);
connect(&thread, SIGNAL(started()), c, SLOT(ProcessActions()));
thread.start();
This produces even more errors:
QThread: Destroyed while thread is still running
ASSERT failure in QThread::setTerminationEnabled(): "Current thread was not started with QThread.", file c:ndk_buildreposqt-desktopsrccorelibthreadqthread_win.cpp, line 542
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
QObject::killTimers: timers cannot be stopped from another thread
I am having problems with this error … I’m stuck on this for 2 days already and can’t get a solution.
Header:
class Citizen : public QThread
{
Q_OBJECT
QNetworkAccessManager * manager;
private slots:
void onReplyFinished(QNetworkReply* net_reply);
public:
Citizen(QObject * parent);
void run();
};
Implementation:
Citizen::Citizen(QObject * parent)
{
manager = new QNetworkAccessManager;
connect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onReplyFinished(QNetworkReply*)));
}
void Citizen::onReplyFinished(QNetworkReply* net_reply)
{
emit onFinished(net_reply);
}
void Citizen::run()
{
manager->get(QNetworkRequest(QUrl("http://google.com"));
QEventLoop eLoop;
connect(manager, SIGNAL( finished( QNetworkReply * ) ), &eLoop, SLOT(quit()));
eLoop.exec(QEventLoop::ExcludeUserInputEvents);
qDebug() << "loaded google!";
exec();
}
When manager->get() gets executed, I get the following error:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0xc996cf8), parent's thread is QThread(0xaba48d8), current thread is Citizen(0xca7ae08)
When eLoop.exec() gets executed:
QObject::startTimer: timers cannot be started from another thread
I start this thread in the following manner:
Citizen * c = new Citizen(this);
c->start();
Why does this happen? How to solve this?
Issue
When I try to change the text of a text browser which is inside a scroll area I get this PyQt5 threading error:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x212e3bb1f50), parent's thread is QThread(0x212e171e220), current thread is QThread(0x212e41dc7e0)
I assume it is because of the scroll area and that I don’t have access to it from the thread I am trying to change this from and it works if I put the same bit of code…
filepath = "..."
with open(filepath, "r") as f:
contents = f.read()
#print(contents)
self.log_1.setText(contents)
(and yes I am aware that the filepath is «…», used for file security.)
…inside the thread that the scrollarea is created inside it works completely fine.
The only thing I don’t know is how to fix this. I think you might be able to inherit the thread to the scroll area in someway, idk.
My code, but simplified:
from PyQt5 import QtCore, QtGui, QtWidgets
from mcstatus import MinecraftServer
import threading
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1379, 523)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.scrollArea_1 = QtWidgets.QScrollArea(self.S1)
self.scrollArea_1.setGeometry(QtCore.QRect(0, 20, 981, 341))
self.scrollArea_1.setWidgetResizable(True)
self.scrollArea_1.setObjectName("scrollArea_1")
self.scrollAreaWidgetContents_1 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_1.setGeometry(QtCore.QRect(0, 0, 979, 339))
self.scrollAreaWidgetContents_1.setObjectName("scrollAreaWidgetContents_1")
self.log_1 = QtWidgets.QTextBrowser(self.scrollAreaWidgetContents_1)
self.log_1.setGeometry(QtCore.QRect(0, 0, 981, 341))
self.log_1.setMinimumSize(QtCore.QSize(981, 341))
self.log_1.viewport().setProperty("cursor",
QtGui.QCursor(QtCore.Qt.IBeamCursor))
self.log_1.setObjectName("log_1")
self.scrollArea_1.setWidget(self.scrollAreaWidgetContents_1)
def update1(self, MainWindow):
threading.Timer(0.2, self.update1, {MainWindow: MainWindow}).start()
ip = "..."
port = 25565 #Server 1
server = MinecraftServer(ip, port)
try:
filepath = "..."
with open(filepath, "r") as f:
contents = f.read()
#print(contents)
self.log_1.setText(contents)
except IOError as e:
self.StatusL_1.setText(self.translate("MainWindow", "<html><head/><body><p><span style=" font-size:18pt;">Status: Off</span></p></body></html>"))
else:
self.StatusL_1.setText(self.translate("MainWindow", "<html><head/><body><p><span style=" font-size:18pt;">Status: On</span></p></body></html>"))
Solution
You should not directly modify the GUI from another thread, one way to modify the GUI indirectly from another thread is to use the Qt signals:
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
from mcstatus import MinecraftServer
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# ...
class Worker(QtCore.QObject):
logged = QtCore.pyqtSignal(str)
statusChanged = QtCore.pyqtSignal(bool)
def start(self):
threading.Timer(0.2, self._execute, daemon=True).start()
def _execute(self):
threading.Timer(0.2, self._execute, daemon=True).start()
ip = "..."
port = 25565 # Server 1
server = MinecraftServer(ip, port)
try:
filepath = "..."
with open(filepath, "r") as f:
contents = f.read()
self.logged.emit(contents)
except IOError as e:
self.statusChanged.emit(False)
else:
self.statusChanged.emit(True)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.worker = Worker()
self.worker.logged.connect(self.log_1.setText)
self.worker.statusChanged.connect(self.on_status_changed)
self.worker.start()
@QtCore.pyqtSlot(bool)
def on_status_changed(self, status):
text = '<html><head/><body><p><span style=" font-size:18pt;">Status: {}</span></p></body></html>'.format(
"On" if status else "Off"
)
self.StatusL_1.setText(text)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Answered By — eyllanesc
![]() |
Автор | Тема: QObject: Cannot create children for a parent that is in a different thread. (Прочитано 10173 раз) |
|
||||||
|
||||||
|
||||||
|
||||||
|
||||||
|
||||||
|
||||||
|
||||||
|
||||||
|
||||||
|
||||||
August 03, 2012 by Andy Shaw
| Comments
After an unfortunately long hiatus mainly due to the vacation period we are finally back and hopefully back on track with having weekly updates. So without further delay then here is this week’s support weekly.
As most of us, if not all of us, would have encountered by now when running Qt applications, warning or error messages in the debug output, some are straightforward to understand and some are a bit more cryptic. So this week I will go over some of the warning messages that may come up that aren’t necessarily the easiest to make sense of and go into some detail as to what causes the warning and how to fix it.
Initializing QFontEngineQPF failed for /app/lib/fonts/fontname.ttf
This is an indication that the application cannot handle ttf fonts, you may see this message more than once as it will occur for all the ttf fonts that it finds. In order to fix this then the system needs to have FreeType made available so that Qt can be configured with it (it will auto-detect it so as long as it is installed and in place it should pick it up). Alternatively, you can configure with -qt-freetype and it will use the version of FreeType that is bundled with the Qt package.
QPainter::begin: Paint device returned engine == 0, type: 2
When you get a message from QPainter saying that the engine returned 0, this means that for some reason it is unable to paint on the paint device in question. Pretty much all the times you see this it would be in relation to a QPixmap or a QImage. In the case of QPixmap/QImage it means that it is null, meaning that it has no size set which is why it cannot paint to it. This is either because no size was specified for it or because the size requested was too big that it would have caused an overflow which meant that it ended up not having that size set. If you call isNull() then most of the time it will return true, but sometimes it is possible that QPixmap will not return true but will still have a problem if the size of the pixmap was too large. Reducing the size will make it work.
QObject: Cannot create children for a parent that is in a different thread. (Parent is …, parent’s thread is …, current thread is …)
This one is a bit more understandable at least, but sometimes it is still not clear as to why it occurs. The key problem is that when you want to use objects inside another thread then they have to be created inside the run() function of the thread in question. For example in this case, the warning would be triggered if the object was created in the main() function (thus making it owned by the main thread) and then when used in the other thread it created a child object. Another way that this could be triggered is that the object is created inside the run() function but has been given a parent object which means that the parent and the child belong to different threads. The way to solve this is to either create the objects inside the run() function or to ensure moveToThread() is called on the object before using it inside the run() function.
locking qpf: Permission denied
This is a problem that can come up with Qt for Embedded Linux applications when they are deployed, basically it is not able to lock a font file for usage. The reason this happens is because NFS is not enabled for the device, if NFS is enabled for the device then it should solve this problem.
If anyone has any other warnings that are not clear then please feel free to let me know in the comments, if there are enough then I can do a follow up post explaining some more. Alternatively you can always contact Qt Commercial Support at http://qt.digia.com/customerportal and ask us directly if you encounter one that you don’t know what to do about.
Finally, I would like to thank everyone who gave feedback about support in the recent customer survey, I will be going through all the results carefully and we will be taking all the feedback on board and will use this to improve on our service to you. And if you ever want to give us further feedback you can either do so by sending it via the customer portal (where I will see it) or if you prefer you can send it via your account manager in Qt Commercial Sales who will pass it on to me.
Until next time, happy coding!